include/vcl/outdev.hxx | 8 ++-- include/vcl/vcllayout.hxx | 2 - sw/source/core/txtnode/fntcache.cxx | 40 +++++++++++++++++++- vcl/inc/sallayout.hxx | 2 - vcl/source/gdi/CommonSalLayout.cxx | 4 +- vcl/source/gdi/sallayout.cxx | 4 +- vcl/source/outdev/text.cxx | 72 ++++++++++-------------------------- vcl/source/window/status.cxx | 10 +++-- 8 files changed, 75 insertions(+), 67 deletions(-)
New commits: commit 436b829f5b904d76039db0818cff5dedf1ae89f1 Author: Miklos Vajna <[email protected]> AuthorDate: Thu Aug 16 17:35:17 2018 +0200 Commit: Miklos Vajna <[email protected]> CommitDate: Thu Aug 16 23:39:15 2018 +0200 sw: save one vcl layout call in SwFntObj::DrawText() Pressing a key in Writer used to lay out the relevant string 4 times (counting GenericSalLayout::LayoutText() invocations), save one of them by pre-calculating the layout and sharing it between GetTextArray() and DrawTextArray(). Change-Id: Ic2194bdcbe94a546d57745463ae81e6b0cadcd92 Reviewed-on: https://gerrit.libreoffice.org/59208 Reviewed-by: Miklos Vajna <[email protected]> Tested-by: Jenkins diff --git a/sw/source/core/txtnode/fntcache.cxx b/sw/source/core/txtnode/fntcache.cxx index 4d0f59fcc56d..985ffab1c87b 100644 --- a/sw/source/core/txtnode/fntcache.cxx +++ b/sw/source/core/txtnode/fntcache.cxx @@ -54,6 +54,7 @@ #include <svx/sdr/attribute/sdrallfillattributeshelper.hxx> #include <doc.hxx> #include <editeng/fhgtitem.hxx> +#include <vcl/vcllayout.hxx> #include <docsh.hxx> #include <strings.hrc> #include <fntcap.hxx> @@ -96,6 +97,36 @@ long EvalGridWidthAdd( const SwTextGridItem *const pGrid, const SwDrawTextInfo & return nGridWidthAdd; } +/** + * Pre-calculates glyph items for the rendered subset of rInf's text, assuming + * outdev state does not change between the outdev calls. + */ +SalLayoutGlyphs* lcl_CreateLayout(SwDrawTextInfo& rInf, const OUString& rText, sal_Int32 nIdx, + sal_Int32 nLen, SalLayoutGlyphs& rTextGlyphs) +{ + // Not the string we want to pre-calculate. + if (rText != rInf.GetText() || nIdx != rInf.GetIdx() || nLen != rInf.GetLen()) + return nullptr; + + // Use pre-calculated result. + if (!rTextGlyphs.empty()) + return &rTextGlyphs; + + // Calculate glyph items. + std::unique_ptr<SalLayout> pLayout = rInf.GetOut().ImplLayout( + rText, nIdx, nLen, Point(0, 0), 0, nullptr, SalLayoutFlags::GlyphItemsOnly); + if (!pLayout) + return nullptr; + + const SalLayoutGlyphs* pGlyphs = pLayout->GetGlyphs(); + if (!pGlyphs) + return nullptr; + + // Remember the calculation result. + rTextGlyphs = *pGlyphs; + + return &rTextGlyphs; +} } void SwFntCache::Flush( ) @@ -779,6 +810,8 @@ void SwFntObj::DrawText( SwDrawTextInfo &rInf ) vcl::Font* pTmpFont = bUseScrFont ? m_pScrFont : m_pPrtFont; + SalLayoutGlyphs aTextGlyphs; + // bDirectPrint and bUseScrFont should have these values: // Outdev / RefDef | Printer | VirtPrinter | Window @@ -1393,8 +1426,10 @@ void SwFntObj::DrawText( SwDrawTextInfo &rInf ) // get screen array std::unique_ptr<long[]> pScrArray(new long[sal_Int32(rInf.GetLen())]); + SalLayoutGlyphs* pGlyphs = lcl_CreateLayout(rInf, rInf.GetText(), sal_Int32(rInf.GetIdx()), + sal_Int32(rInf.GetLen()), aTextGlyphs); rInf.GetOut().GetTextArray( rInf.GetText(), pScrArray.get(), - sal_Int32(rInf.GetIdx()), sal_Int32(rInf.GetLen())); + sal_Int32(rInf.GetIdx()), sal_Int32(rInf.GetLen()), nullptr, pGlyphs); // OLE: no printer available // OSL_ENSURE( pPrinter, "DrawText needs pPrinter" ) @@ -1743,8 +1778,9 @@ void SwFntObj::DrawText( SwDrawTextInfo &rInf ) sal_Int32 nTmpIdx = bBullet ? (rInf.GetIdx() ? 1 : 0) : sal_Int32(rInf.GetIdx()); + pGlyphs = lcl_CreateLayout(rInf, *pStr, nTmpIdx, nLen, aTextGlyphs); rInf.GetOut().DrawTextArray( aTextOriginPos, *pStr, pKernArray.get(), - nTmpIdx , nLen ); + nTmpIdx , nLen, SalLayoutFlags::NONE, nullptr, pGlyphs ); if (bBullet) { rInf.GetOut().Push(); commit c5dc042219e9872937f9fe1cb68f2f03423f398e Author: Miklos Vajna <[email protected]> AuthorDate: Thu Aug 16 17:34:49 2018 +0200 Commit: Miklos Vajna <[email protected]> CommitDate: Thu Aug 16 23:39:04 2018 +0200 vcl: use SalLayoutGlyphs, not SalLayout for pre-computed layout This means that the pre-computed glyph ids and positions are usable with multiple dx array or draw base. So the amount of cached data is smaller, but it can be used in more situations, most importantly Writer's SwFntObj::DrawText() use-case (which does GetTextArray() followed by a DrawTextArray(), with different dx array arguments). Change-Id: I3bcd1b7a015c2cf9921efa0f3f355f2c627fb652 Reviewed-on: https://gerrit.libreoffice.org/59207 Reviewed-by: Miklos Vajna <[email protected]> Tested-by: Jenkins diff --git a/include/vcl/outdev.hxx b/include/vcl/outdev.hxx index 6a91fd2527e8..553baf20e591 100644 --- a/include/vcl/outdev.hxx +++ b/include/vcl/outdev.hxx @@ -976,7 +976,7 @@ public: void DrawText( const Point& rStartPt, const OUString& rStr, sal_Int32 nIndex = 0, sal_Int32 nLen = -1, MetricVector* pVector = nullptr, OUString* pDisplayText = nullptr, - SalLayout* pLayoutCache = nullptr ); + const SalLayoutGlyphs* pLayoutCache = nullptr ); void DrawText( const tools::Rectangle& rRect, const OUString& rStr, DrawTextFlags nStyle = DrawTextFlags::NONE, @@ -1138,7 +1138,7 @@ public: */ long GetTextWidth( const OUString& rStr, sal_Int32 nIndex = 0, sal_Int32 nLen = -1, vcl::TextLayoutCache const* = nullptr, - SalLayout const*const pLayoutCache = nullptr) const; + SalLayoutGlyphs const*const pLayoutCache = nullptr) const; /** Height where any character of the current font fits; in logic coordinates. @@ -1154,11 +1154,11 @@ public: sal_Int32 nLen = -1, SalLayoutFlags flags = SalLayoutFlags::NONE, vcl::TextLayoutCache const* = nullptr, - SalLayout* pLayoutCache = nullptr); + const SalLayoutGlyphs* pLayoutCache = nullptr); long GetTextArray( const OUString& rStr, long* pDXAry, sal_Int32 nIndex = 0, sal_Int32 nLen = -1, vcl::TextLayoutCache const* = nullptr, - SalLayout const*const pLayoutCache = nullptr) const; + SalLayoutGlyphs const*const pLayoutCache = nullptr) const; void GetCaretPositions( const OUString&, long* pCaretXArray, sal_Int32 nIndex, sal_Int32 nLen ) const; diff --git a/include/vcl/vcllayout.hxx b/include/vcl/vcllayout.hxx index 735dc4cf748f..fad06ef4646c 100644 --- a/include/vcl/vcllayout.hxx +++ b/include/vcl/vcllayout.hxx @@ -159,7 +159,7 @@ public: virtual std::shared_ptr<vcl::TextLayoutCache> CreateTextLayoutCache(OUString const&) const; - virtual SalLayoutGlyphs GetGlyphs() const; + virtual const SalLayoutGlyphs* GetGlyphs() const; protected: // used by layout engines diff --git a/vcl/inc/sallayout.hxx b/vcl/inc/sallayout.hxx index a8b9e233f450..a6505eb92d35 100644 --- a/vcl/inc/sallayout.hxx +++ b/vcl/inc/sallayout.hxx @@ -175,7 +175,7 @@ public: bool LayoutText(ImplLayoutArgs&, const SalLayoutGlyphs*) final override; void DrawText(SalGraphics&) const final override; std::shared_ptr<vcl::TextLayoutCache> CreateTextLayoutCache(OUString const&) const final override; - SalLayoutGlyphs GetGlyphs() const final override; + const SalLayoutGlyphs* GetGlyphs() const final override; bool IsKashidaPosValid(int nCharPos) const final override; diff --git a/vcl/source/gdi/CommonSalLayout.cxx b/vcl/source/gdi/CommonSalLayout.cxx index fc38b33437e1..e4312847d72b 100644 --- a/vcl/source/gdi/CommonSalLayout.cxx +++ b/vcl/source/gdi/CommonSalLayout.cxx @@ -169,9 +169,9 @@ std::shared_ptr<vcl::TextLayoutCache> GenericSalLayout::CreateTextLayoutCache(OU return std::make_shared<vcl::TextLayoutCache>(rString.getStr(), rString.getLength()); } -SalLayoutGlyphs GenericSalLayout::GetGlyphs() const +const SalLayoutGlyphs* GenericSalLayout::GetGlyphs() const { - return m_GlyphItems; + return &m_GlyphItems; } void GenericSalLayout::SetNeedFallback(ImplLayoutArgs& rArgs, sal_Int32 nCharPos, bool bRightToLeft) diff --git a/vcl/source/gdi/sallayout.cxx b/vcl/source/gdi/sallayout.cxx index 09cf35d8fdfe..b9cc988fdbbb 100644 --- a/vcl/source/gdi/sallayout.cxx +++ b/vcl/source/gdi/sallayout.cxx @@ -1579,10 +1579,10 @@ std::shared_ptr<vcl::TextLayoutCache> SalLayout::CreateTextLayoutCache( return nullptr; // by default, nothing to cache } -SalLayoutGlyphs SalLayout::GetGlyphs() const +const SalLayoutGlyphs* SalLayout::GetGlyphs() const { // No access to the glyphs by default. - return SalLayoutGlyphs(); + return nullptr; } /* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/vcl/source/outdev/text.cxx b/vcl/source/outdev/text.cxx index f1747895e947..9568b3b50eb2 100644 --- a/vcl/source/outdev/text.cxx +++ b/vcl/source/outdev/text.cxx @@ -788,7 +788,7 @@ void OutputDevice::SetTextAlign( TextAlign eAlign ) void OutputDevice::DrawText( const Point& rStartPt, const OUString& rStr, sal_Int32 nIndex, sal_Int32 nLen, MetricVector* pVector, OUString* pDisplayText, - SalLayout* pLayoutCache + const SalLayoutGlyphs* pLayoutCache ) { assert(!is_double_buffered_window()); @@ -873,27 +873,10 @@ void OutputDevice::DrawText( const Point& rStartPt, const OUString& rStr, pLayoutCache = nullptr; #endif - // without cache - if(!pLayoutCache) + std::unique_ptr<SalLayout> pSalLayout = ImplLayout(rStr, nIndex, nLen, rStartPt, 0, nullptr, SalLayoutFlags::NONE, nullptr, pLayoutCache); + if(pSalLayout) { - std::unique_ptr<SalLayout> pSalLayout = ImplLayout(rStr, nIndex, nLen, rStartPt); - if(pSalLayout) - { - ImplDrawText( *pSalLayout ); - } - } - else - { - // initialize font if needed - if( mbNewFont ) - if( !ImplNewFont() ) - return; - if( mbInitFont ) - InitFont(); - - pLayoutCache->DrawBase() = ImplLogicToDevicePixel( rStartPt ); - - ImplDrawText( *pLayoutCache ); + ImplDrawText( *pSalLayout ); } if( mpAlphaVDev ) @@ -902,7 +885,7 @@ void OutputDevice::DrawText( const Point& rStartPt, const OUString& rStr, long OutputDevice::GetTextWidth( const OUString& rStr, sal_Int32 nIndex, sal_Int32 nLen, vcl::TextLayoutCache const*const pLayoutCache, - SalLayout const*const pSalLayoutCache) const + SalLayoutGlyphs const*const pSalLayoutCache) const { long nWidth = GetTextArray( rStr, nullptr, nIndex, @@ -946,7 +929,7 @@ void OutputDevice::DrawTextArray( const Point& rStartPt, const OUString& rStr, const long* pDXAry, sal_Int32 nIndex, sal_Int32 nLen, SalLayoutFlags flags, vcl::TextLayoutCache const*const pLayoutCache, - SalLayout* pSalLayoutCache ) + const SalLayoutGlyphs* pSalLayoutCache ) { assert(!is_double_buffered_window()); @@ -966,13 +949,7 @@ void OutputDevice::DrawTextArray( const Point& rStartPt, const OUString& rStr, if( mbOutputClipped ) return; - SalLayout* pSalLayout = pSalLayoutCache; - std::unique_ptr<SalLayout> pLayout; - if (!pSalLayout) - { - pLayout = ImplLayout(rStr, nIndex, nLen, rStartPt, 0, pDXAry, flags, pLayoutCache); - pSalLayout = pLayout.get(); - } + std::unique_ptr<SalLayout> pSalLayout = ImplLayout(rStr, nIndex, nLen, rStartPt, 0, pDXAry, flags, pLayoutCache, pSalLayoutCache); if( pSalLayout ) { ImplDrawText( *pSalLayout ); @@ -985,7 +962,7 @@ void OutputDevice::DrawTextArray( const Point& rStartPt, const OUString& rStr, long OutputDevice::GetTextArray( const OUString& rStr, long* pDXAry, sal_Int32 nIndex, sal_Int32 nLen, vcl::TextLayoutCache const*const pLayoutCache, - SalLayout const*const pSalLayoutCache) const + SalLayoutGlyphs const*const pSalLayoutCache) const { if( nIndex >= rStr.getLength() ) return 0; // TODO: this looks like a buggy caller? @@ -995,29 +972,22 @@ long OutputDevice::GetTextArray( const OUString& rStr, long* pDXAry, nLen = rStr.getLength() - nIndex; } - std::unique_ptr<SalLayout> xSalLayout; - const SalLayout* pSalLayout = pSalLayoutCache; - - if(!pSalLayoutCache) + // do layout + std::unique_ptr<SalLayout> pSalLayout = ImplLayout(rStr, nIndex, nLen, + Point(0,0), 0, nullptr, SalLayoutFlags::NONE, pLayoutCache, pSalLayoutCache); + if( !pSalLayout ) { - // do layout - xSalLayout = ImplLayout(rStr, nIndex, nLen, - Point(0,0), 0, nullptr, SalLayoutFlags::NONE, pLayoutCache); - pSalLayout = xSalLayout.get(); - if( !pSalLayout ) + // The caller expects this to init the elements of pDXAry. + // Adapting all the callers to check that GetTextArray succeeded seems + // too much work. + // Init here to 0 only in the (rare) error case, so that any missing + // element init in the happy case will still be found by tools, + // and hope that is sufficient. + if (pDXAry) { - // The caller expects this to init the elements of pDXAry. - // Adapting all the callers to check that GetTextArray succeeded seems - // too much work. - // Init here to 0 only in the (rare) error case, so that any missing - // element init in the happy case will still be found by tools, - // and hope that is sufficient. - if (pDXAry) - { - memset(pDXAry, 0, nLen * sizeof(*pDXAry)); - } - return 0; + memset(pDXAry, 0, nLen * sizeof(*pDXAry)); } + return 0; } #if VCL_FLOAT_DEVICE_PIXEL diff --git a/vcl/source/window/status.cxx b/vcl/source/window/status.cxx index 4a9d24bd4f7e..666824613b34 100644 --- a/vcl/source/window/status.cxx +++ b/vcl/source/window/status.cxx @@ -408,7 +408,8 @@ void StatusBar::ImplDrawItem(vcl::RenderContext& rRenderContext, bool bOffScreen pLayoutCache = pItem->mxLayoutCache.get(); } - Size aTextSize(rRenderContext.GetTextWidth(pItem->maText,0,-1,nullptr,pLayoutCache), rRenderContext.GetTextHeight()); + const SalLayoutGlyphs* pGlyphs = pLayoutCache ? pLayoutCache->GetGlyphs() : nullptr; + Size aTextSize(rRenderContext.GetTextWidth(pItem->maText,0,-1,nullptr,pGlyphs), rRenderContext.GetTextHeight()); Point aTextPos = ImplGetItemTextPos(aTextRectSize, aTextSize, pItem->mnBits); @@ -418,7 +419,7 @@ void StatusBar::ImplDrawItem(vcl::RenderContext& rRenderContext, bool bOffScreen aTextPos, pItem->maText, 0, -1, nullptr, nullptr, - pLayoutCache ); + pGlyphs ); } else { @@ -428,7 +429,7 @@ void StatusBar::ImplDrawItem(vcl::RenderContext& rRenderContext, bool bOffScreen aTextPos, pItem->maText, 0, -1, nullptr, nullptr, - pLayoutCache ); + pGlyphs ); } // call DrawItem if necessary @@ -1192,7 +1193,8 @@ void StatusBar::SetItemText( sal_uInt16 nItemId, const OUString& rText ) long nFudge = GetTextHeight()/4; std::unique_ptr<SalLayout> pSalLayout = ImplLayout(pItem->maText,0,-1); - long nWidth = GetTextWidth( pItem->maText,0,-1,nullptr,pSalLayout.get() ) + nFudge; + const SalLayoutGlyphs* pGlyphs = pSalLayout ? pSalLayout->GetGlyphs() : nullptr; + long nWidth = GetTextWidth( pItem->maText,0,-1,nullptr,pGlyphs ) + nFudge; // Store the calculated layout. pItem->mxLayoutCache = std::move(pSalLayout); _______________________________________________ Libreoffice-commits mailing list [email protected] https://lists.freedesktop.org/mailman/listinfo/libreoffice-commits
