include/vcl/glyphitem.hxx | 19 ++++++---- include/vcl/outdev.hxx | 6 ++- include/vcl/vcllayout.hxx | 6 +-- sc/source/ui/view/output2.cxx | 4 +- svtools/source/control/ruler.cxx | 6 --- sw/source/core/txtnode/fntcache.cxx | 6 --- vcl/inc/impglyphitem.hxx | 7 +-- vcl/inc/sallayout.hxx | 13 ++++-- vcl/qa/cppunit/complextext.cxx | 10 ++--- vcl/source/control/imp_listbox.cxx | 6 --- vcl/source/gdi/CommonSalLayout.cxx | 68 ++++++++++++++++++------------------ vcl/source/gdi/impglyphitem.cxx | 42 ++++++++++------------ vcl/source/gdi/sallayout.cxx | 64 +++++++++++++++++++-------------- vcl/source/outdev/font.cxx | 9 ++-- vcl/source/outdev/text.cxx | 4 +- vcl/source/window/menuitemlist.cxx | 6 --- vcl/source/window/status.cxx | 16 ++++---- 17 files changed, 147 insertions(+), 145 deletions(-)
New commits: commit 7439cabc643de2f07c18adc35056f802997f484a Author: Luboš Luňák <l.lu...@collabora.com> AuthorDate: Tue Mar 16 15:04:08 2021 +0100 Commit: Luboš Luňák <l.lu...@collabora.com> CommitDate: Wed Mar 17 22:49:33 2021 +0100 make SalLayoutGlyphs work with MultiSalLayout Code that needs to lay out texts repeatedly can cache the result of SalLayout::GetGlyphs() can reuse it. But GetGlyphs() returns nullptr for MultiSalLayout, so caching for it doesn't work. Worse still, it actually increases the number of layout calls, because there's the initial layout for caching and then each call will need to do the layout again because of the nullptr that's not cached. This commit changes SalLayoutGlyphs to possibly include multiple SalLayoutGlyphsImpl objects, one for each SalLayout handled by MultiSalLayout. Changes include making GenericSalLayout work directly with the Impl class, which avoids an indirection and simplifies code. Change-Id: Ic4b19934a8a06d4955b51527fe3777c5e91107b2 Reviewed-on: https://gerrit.libreoffice.org/c/core/+/112590 Tested-by: Jenkins Reviewed-by: Luboš Luňák <l.lu...@collabora.com> diff --git a/include/vcl/glyphitem.hxx b/include/vcl/glyphitem.hxx index 7634bd3a4413..02d783a3e166 100644 --- a/include/vcl/glyphitem.hxx +++ b/include/vcl/glyphitem.hxx @@ -23,23 +23,30 @@ #include <sal/types.h> #include <vcl/dllapi.h> +#include <vector> + typedef sal_uInt16 sal_GlyphId; class SalLayoutGlyphsImpl; class VCL_DLLPUBLIC SalLayoutGlyphs final { - friend class SalLayoutGlyphsImpl; - SalLayoutGlyphsImpl* m_pImpl; + std::vector<SalLayoutGlyphsImpl*> m_pImpls; public: - SalLayoutGlyphs(); - SalLayoutGlyphs(const SalLayoutGlyphs&); + SalLayoutGlyphs() = default; + SalLayoutGlyphs(const SalLayoutGlyphs&) = delete; + SalLayoutGlyphs(SalLayoutGlyphs&&); ~SalLayoutGlyphs(); - SalLayoutGlyphs& operator=(const SalLayoutGlyphs&); + SalLayoutGlyphs& operator=(const SalLayoutGlyphs&) = delete; + SalLayoutGlyphs& operator=(SalLayoutGlyphs&&); - SalLayoutGlyphsImpl* Impl() const { return m_pImpl; } + SalLayoutGlyphsImpl* Impl(unsigned int nLevel) const + { + return nLevel < m_pImpls.size() ? m_pImpls[nLevel] : nullptr; + } + void AppendImpl(SalLayoutGlyphsImpl* pImpl) { m_pImpls.push_back(pImpl); } bool IsValid() const; void Invalidate(); diff --git a/include/vcl/outdev.hxx b/include/vcl/outdev.hxx index a8d77c77b30e..ce7d54e75689 100644 --- a/include/vcl/outdev.hxx +++ b/include/vcl/outdev.hxx @@ -1352,11 +1352,13 @@ public: SalLayoutFlags flags = SalLayoutFlags::NONE, vcl::TextLayoutCache const* = nullptr) const; SAL_DLLPRIVATE std::unique_ptr<SalLayout> - ImplGlyphFallbackLayout( std::unique_ptr<SalLayout>, ImplLayoutArgs& ) const; + ImplGlyphFallbackLayout( std::unique_ptr<SalLayout>, + ImplLayoutArgs&, + const SalLayoutGlyphs* ) const; SAL_DLLPRIVATE std::unique_ptr<SalLayout> getFallbackLayout( LogicalFontInstance* pLogicalFont, int nFallbackLevel, - ImplLayoutArgs& rLayoutArgs) const; + ImplLayoutArgs& rLayoutArgs, const SalLayoutGlyphs* ) const; // Enabling/disabling RTL only makes sense for OutputDevices that use a mirroring SalGraphicsLayout diff --git a/include/vcl/vcllayout.hxx b/include/vcl/vcllayout.hxx index 7d53d12bd40b..e09e54f59d65 100644 --- a/include/vcl/vcllayout.hxx +++ b/include/vcl/vcllayout.hxx @@ -24,13 +24,13 @@ #include <tools/gen.hxx> #include <tools/degree.hxx> #include <vcl/devicecoordinate.hxx> +#include <vcl/glyphitem.hxx> #include <vcl/dllapi.h> class ImplLayoutArgs; class PhysicalFontFace; class SalGraphics; class GlyphItem; -class SalLayoutGlyphs; // all positions/widths are in font units // one exception: drawposition is in pixel units @@ -73,7 +73,7 @@ public: const Point& DrawOffset() const { return maDrawOffset; } Point GetDrawPosition( const Point& rRelative = Point(0,0) ) const; - virtual bool LayoutText( ImplLayoutArgs&, const SalLayoutGlyphs* ) = 0; // first step of layouting + virtual bool LayoutText( ImplLayoutArgs&, const SalLayoutGlyphsImpl* ) = 0; // first step of layouting virtual void AdjustLayout( ImplLayoutArgs& ); // adjusting after fallback etc. virtual void InitFont() const {} virtual void DrawText( SalGraphics& ) const = 0; @@ -94,7 +94,7 @@ public: virtual bool GetOutline(basegfx::B2DPolyPolygonVector&) const; bool GetBoundRect(tools::Rectangle&) const; - virtual const SalLayoutGlyphs* GetGlyphs() const; + virtual SalLayoutGlyphs GetGlyphs() const; protected: // used by layout engines diff --git a/sc/source/ui/view/output2.cxx b/sc/source/ui/view/output2.cxx index 46f4bc0b3e0e..4d5003bdc02e 100644 --- a/sc/source/ui/view/output2.cxx +++ b/sc/source/ui/view/output2.cxx @@ -779,9 +779,9 @@ const SalLayoutGlyphs* ScDrawStringsVars::GetLayoutGlyphs(const OUString& rStrin return &it->second; std::unique_ptr<SalLayout> layout = pOutput->pFmtDevice->ImplLayout( rString, 0, rString.getLength(), Point( 0, 0 ), 0, nullptr, SalLayoutFlags::GlyphItemsOnly ); - if( layout && layout->GetGlyphs()) + if( layout ) { - mCachedGlyphs.insert( std::make_pair( rString, *layout->GetGlyphs())); + mCachedGlyphs.insert( std::make_pair( rString, layout->GetGlyphs())); assert(mCachedGlyphs.find( rString ) == mCachedGlyphs.begin()); // newly inserted item is first return &mCachedGlyphs.begin()->second; } diff --git a/svtools/source/control/ruler.cxx b/svtools/source/control/ruler.cxx index 1f4a5d4eafac..2551dc39581d 100644 --- a/svtools/source/control/ruler.cxx +++ b/svtools/source/control/ruler.cxx @@ -84,12 +84,8 @@ SalLayoutGlyphs* lcl_GetRulerTextGlyphs(const vcl::RenderContext& rRenderContext if (!pLayout) return nullptr; - const SalLayoutGlyphs* pGlyphs = pLayout->GetGlyphs(); - if (!pGlyphs) - return nullptr; - // Remember the calculation result. - rTextGlyphs = *pGlyphs; + rTextGlyphs = pLayout->GetGlyphs(); return &rTextGlyphs; } diff --git a/sw/source/core/txtnode/fntcache.cxx b/sw/source/core/txtnode/fntcache.cxx index 2327ce0de4ce..eeeb3f833193 100644 --- a/sw/source/core/txtnode/fntcache.cxx +++ b/sw/source/core/txtnode/fntcache.cxx @@ -234,12 +234,8 @@ static SalLayoutGlyphs* lcl_CreateLayout(const SwTextGlyphsKey& rKey, std::map<S if (!pLayout) return nullptr; - const SalLayoutGlyphs* pGlyphs = pLayout->GetGlyphs(); - if (!pGlyphs) - return nullptr; - // Remember the calculation result. - it->second.m_aTextGlyphs = *pGlyphs; + it->second.m_aTextGlyphs = pLayout->GetGlyphs(); return &it->second.m_aTextGlyphs; } diff --git a/vcl/inc/impglyphitem.hxx b/vcl/inc/impglyphitem.hxx index da56b660d7b6..c3bd423d7e5a 100644 --- a/vcl/inc/impglyphitem.hxx +++ b/vcl/inc/impglyphitem.hxx @@ -119,19 +119,18 @@ class SalLayoutGlyphsImpl : public std::vector<GlyphItem> friend class GenericSalLayout; public: - SalLayoutGlyphsImpl* clone(SalLayoutGlyphs& rGlyphs) const; + SalLayoutGlyphsImpl* clone() const; LogicalFontInstance& GetFont() const { return *m_rFontInstance; } bool IsValid() const; void Invalidate(); private: - mutable rtl::Reference<LogicalFontInstance> m_rFontInstance; + rtl::Reference<LogicalFontInstance> m_rFontInstance; SalLayoutFlags mnFlags = SalLayoutFlags::NONE; - SalLayoutGlyphsImpl(SalLayoutGlyphs& rGlyphs, LogicalFontInstance& rFontInstance) + SalLayoutGlyphsImpl(LogicalFontInstance& rFontInstance) : m_rFontInstance(&rFontInstance) { - rGlyphs.m_pImpl = this; } }; diff --git a/vcl/inc/sallayout.hxx b/vcl/inc/sallayout.hxx index 30fd5580b4c5..d480089c0b38 100644 --- a/vcl/inc/sallayout.hxx +++ b/vcl/inc/sallayout.hxx @@ -134,13 +134,14 @@ public: const PhysicalFontFace** pFallbackFont = nullptr) const override; bool GetOutline(basegfx::B2DPolyPolygonVector&) const override; bool IsKashidaPosValid(int nCharPos) const override; + SalLayoutGlyphs GetGlyphs() const final override; // used only by OutputDevice::ImplLayout, TODO: make friend explicit MultiSalLayout( std::unique_ptr<SalLayout> pBaseLayout ); void AddFallback(std::unique_ptr<SalLayout> pFallbackLayout, ImplLayoutRuns const &); // give up ownership of the initial pBaseLayout taken by the ctor std::unique_ptr<SalLayout> ReleaseBaseLayout(); - bool LayoutText(ImplLayoutArgs&, const SalLayoutGlyphs*) override; + bool LayoutText(ImplLayoutArgs&, const SalLayoutGlyphsImpl*) override; void AdjustLayout(ImplLayoutArgs&) override; void InitFont() const override; @@ -168,10 +169,10 @@ public: ~GenericSalLayout() override; void AdjustLayout(ImplLayoutArgs&) final override; - bool LayoutText(ImplLayoutArgs&, const SalLayoutGlyphs*) final override; + bool LayoutText(ImplLayoutArgs&, const SalLayoutGlyphsImpl*) final override; void DrawText(SalGraphics&) const final override; static std::shared_ptr<vcl::TextLayoutCache> CreateTextLayoutCache(OUString const&); - const SalLayoutGlyphs* GetGlyphs() const final override; + SalLayoutGlyphs GetGlyphs() const final override; bool IsKashidaPosValid(int nCharPos) const final override; @@ -183,11 +184,13 @@ public: // used by display layers LogicalFontInstance& GetFont() const - { return m_GlyphItems.Impl()->GetFont(); } + { return m_GlyphItems.GetFont(); } bool GetNextGlyph(const GlyphItem** pGlyph, Point& rPos, int& nStart, const PhysicalFontFace** pFallbackFont = nullptr) const override; + const SalLayoutGlyphsImpl& GlyphsImpl() const { return m_GlyphItems; } + private: // for glyph+font+script fallback void MoveGlyph(int nStart, tools::Long nNewXPos); @@ -211,7 +214,7 @@ private: css::uno::Reference<css::i18n::XBreakIterator> mxBreak; - SalLayoutGlyphs m_GlyphItems; + SalLayoutGlyphsImpl m_GlyphItems; OString msLanguage; std::vector<hb_feature_t> maFeatures; diff --git a/vcl/qa/cppunit/complextext.cxx b/vcl/qa/cppunit/complextext.cxx index f769fe4688b4..f953c3060eb4 100644 --- a/vcl/qa/cppunit/complextext.cxx +++ b/vcl/qa/cppunit/complextext.cxx @@ -121,17 +121,15 @@ void VclComplexTextTest::testKashida() = OUString(u"ﻊﻨﺻﺭ ﺎﻠﻓﻮﺴﻓﻭﺭ ﻊﻨﺻﺭ ﻒﻟﺰﻳ ﺺﻠﺑ. ﺖﺘﻛﻮﻧ ﺎﻟﺩﻭﺭﺓ ﺎﻟﺭﺎﺒﻋﺓ ﻢﻧ ١٥ ﻊﻨﺻﺭﺍ."); std::unique_ptr<SalLayout> pLayout = pOutputDevice->ImplLayout( aText, 0, aText.getLength(), Point(0, 0), 0, nullptr, SalLayoutFlags::GlyphItemsOnly); - const SalLayoutGlyphs* pGlyphs = pLayout->GetGlyphs(); - if (!pGlyphs) - // Failed in some non-interesting ways. - return; - SalLayoutGlyphs aGlyphs = *pGlyphs; + SalLayoutGlyphs aGlyphs = pLayout->GetGlyphs(); + CPPUNIT_ASSERT(aGlyphs.IsValid()); + CPPUNIT_ASSERT(aGlyphs.Impl(0) != nullptr); // Now lay it out using the cached glyph list. ImplLayoutArgs aLayoutArgs(aText, 0, aText.getLength(), SalLayoutFlags::NONE, pOutputDevice->GetFont().GetLanguageTag(), nullptr); pLayout = pOutputDevice->GetGraphics()->GetTextLayout(0); - CPPUNIT_ASSERT(pLayout->LayoutText(aLayoutArgs, &aGlyphs)); + CPPUNIT_ASSERT(pLayout->LayoutText(aLayoutArgs, aGlyphs.Impl(0))); // Without the accompanying fix in place, this test would have failed with 'assertion failed'. // The kashida justification flag was lost when going via the glyph cache. diff --git a/vcl/source/control/imp_listbox.cxx b/vcl/source/control/imp_listbox.cxx index 0c5e8f1237f6..8f2269941986 100644 --- a/vcl/source/control/imp_listbox.cxx +++ b/vcl/source/control/imp_listbox.cxx @@ -592,12 +592,8 @@ SalLayoutGlyphs* ImplEntryType::GetTextGlyphs(const OutputDevice* pOutputDevice) if (!pLayout) return nullptr; - const SalLayoutGlyphs* pGlyphs = pLayout->GetGlyphs(); - if (!pGlyphs) - return nullptr; - // Remember the calculation result. - maStrGlyphs = *pGlyphs; + maStrGlyphs = pLayout->GetGlyphs(); return &maStrGlyphs; } diff --git a/vcl/source/gdi/CommonSalLayout.cxx b/vcl/source/gdi/CommonSalLayout.cxx index 7f557c73b314..2ef3c98d2f9d 100644 --- a/vcl/source/gdi/CommonSalLayout.cxx +++ b/vcl/source/gdi/CommonSalLayout.cxx @@ -57,10 +57,10 @@ static hb_unicode_funcs_t* getUnicodeFuncs() #endif GenericSalLayout::GenericSalLayout(LogicalFontInstance &rFont) - : mpVertGlyphs(nullptr) + : m_GlyphItems(rFont) + , mpVertGlyphs(nullptr) , mbFuzzing(utl::ConfigManager::IsFuzzing()) { - new SalLayoutGlyphsImpl(m_GlyphItems, rFont); } GenericSalLayout::~GenericSalLayout() @@ -190,9 +190,11 @@ std::shared_ptr<vcl::TextLayoutCache> GenericSalLayout::CreateTextLayoutCache(OU return std::make_shared<vcl::TextLayoutCache>(rString.getStr(), rString.getLength()); } -const SalLayoutGlyphs* GenericSalLayout::GetGlyphs() const +SalLayoutGlyphs GenericSalLayout::GetGlyphs() const { - return &m_GlyphItems; + SalLayoutGlyphs glyphs; + glyphs.AppendImpl(m_GlyphItems.clone()); + return glyphs; } void GenericSalLayout::SetNeedFallback(ImplLayoutArgs& rArgs, sal_Int32 nCharPos, bool bRightToLeft) @@ -284,7 +286,7 @@ bool GenericSalLayout::HasVerticalAlternate(sal_UCS4 aChar, sal_UCS4 aVariationS return hb_set_has(mpVertGlyphs, nGlyphIndex) != 0; } -bool GenericSalLayout::LayoutText(ImplLayoutArgs& rArgs, const SalLayoutGlyphs* pGlyphs) +bool GenericSalLayout::LayoutText(ImplLayoutArgs& rArgs, const SalLayoutGlyphsImpl* pGlyphs) { // No need to touch m_GlyphItems at all for an empty string. if (rArgs.mnEndCharPos - rArgs.mnMinCharPos <= 0) @@ -295,7 +297,7 @@ bool GenericSalLayout::LayoutText(ImplLayoutArgs& rArgs, const SalLayoutGlyphs* // Work with pre-computed glyph items. m_GlyphItems = *pGlyphs; // Some flags are set as a side effect of text layout, restore them here. - rArgs.mnFlags |= pGlyphs->Impl()->mnFlags; + rArgs.mnFlags |= pGlyphs->mnFlags; return true; } @@ -303,7 +305,7 @@ bool GenericSalLayout::LayoutText(ImplLayoutArgs& rArgs, const SalLayoutGlyphs* bool isGraphite = GetFont().IsGraphiteFont(); int nGlyphCapacity = 2 * (rArgs.mnEndCharPos - rArgs.mnMinCharPos); - m_GlyphItems.Impl()->reserve(nGlyphCapacity); + m_GlyphItems.reserve(nGlyphCapacity); const int nLength = rArgs.mrStr.getLength(); const sal_Unicode *pStr = rArgs.mrStr.getStr(); @@ -603,7 +605,7 @@ bool GenericSalLayout::LayoutText(ImplLayoutArgs& rArgs, const SalLayoutGlyphs* Point aNewPos(aCurrPos.X() + nXOffset, aCurrPos.Y() + nYOffset); const GlyphItem aGI(nCharPos, nCharCount, nGlyphIndex, aNewPos, nGlyphFlags, nAdvance, nXOffset, &GetFont()); - m_GlyphItems.Impl()->push_back(aGI); + m_GlyphItems.push_back(aGI); aCurrPos.AdjustX(nAdvance ); } @@ -614,7 +616,7 @@ bool GenericSalLayout::LayoutText(ImplLayoutArgs& rArgs, const SalLayoutGlyphs* // Some flags are set as a side effect of text layout, save them here. if (rArgs.mnFlags & SalLayoutFlags::GlyphItemsOnly) - m_GlyphItems.Impl()->mnFlags = rArgs.mnFlags; + m_GlyphItems.mnFlags = rArgs.mnFlags; return true; } @@ -626,7 +628,7 @@ void GenericSalLayout::GetCharWidths(DeviceCoordinate* pCharWidths) const for (int i = 0; i < nCharCount; ++i) pCharWidths[i] = 0; - for (auto const& aGlyphItem : *m_GlyphItems.Impl()) + for (auto const& aGlyphItem : m_GlyphItems) { const int nIndex = aGlyphItem.charPos() - mnMinCharPos; if (nIndex >= nCharCount) @@ -694,31 +696,31 @@ void GenericSalLayout::ApplyDXArray(const ImplLayoutArgs& rArgs) // Apply the DX adjustments to glyph positions and widths. size_t i = 0; - while (i < m_GlyphItems.Impl()->size()) + while (i < m_GlyphItems.size()) { // Accumulate the width difference for all characters corresponding to // this glyph. - int nCharPos = (*m_GlyphItems.Impl())[i].charPos() - mnMinCharPos; + int nCharPos = m_GlyphItems[i].charPos() - mnMinCharPos; DeviceCoordinate nDiff = 0; - for (int j = 0; j < (*m_GlyphItems.Impl())[i].charCount(); j++) + for (int j = 0; j < m_GlyphItems[i].charCount(); j++) nDiff += pNewCharWidths[nCharPos + j] - pOldCharWidths[nCharPos + j]; - if (!(*m_GlyphItems.Impl())[i].IsRTLGlyph()) + if (!m_GlyphItems[i].IsRTLGlyph()) { // Adjust the width and position of the first (leftmost) glyph in // the cluster. - (*m_GlyphItems.Impl())[i].m_nNewWidth += nDiff; - (*m_GlyphItems.Impl())[i].m_aLinearPos.AdjustX(nDelta); + m_GlyphItems[i].m_nNewWidth += nDiff; + m_GlyphItems[i].m_aLinearPos.AdjustX(nDelta); // Adjust the position of the rest of the glyphs in the cluster. - while (++i < m_GlyphItems.Impl()->size()) + while (++i < m_GlyphItems.size()) { - if (!(*m_GlyphItems.Impl())[i].IsInCluster()) + if (!m_GlyphItems[i].IsInCluster()) break; - (*m_GlyphItems.Impl())[i].m_aLinearPos.AdjustX(nDelta); + m_GlyphItems[i].m_aLinearPos.AdjustX(nDelta); } } - else if ((*m_GlyphItems.Impl())[i].IsInCluster()) + else if (m_GlyphItems[i].IsInCluster()) { // RTL glyph in the middle of the cluster, will be handled in the // loop below. @@ -729,34 +731,34 @@ void GenericSalLayout::ApplyDXArray(const ImplLayoutArgs& rArgs) // Adjust the width and position of the first (rightmost) glyph in // the cluster. // For RTL, we put all the adjustment to the left of the glyph. - (*m_GlyphItems.Impl())[i].m_nNewWidth += nDiff; - (*m_GlyphItems.Impl())[i].m_aLinearPos.AdjustX(nDelta + nDiff); + m_GlyphItems[i].m_nNewWidth += nDiff; + m_GlyphItems[i].m_aLinearPos.AdjustX(nDelta + nDiff); // Adjust the X position of all glyphs in the cluster. size_t j = i; while (j > 0) { --j; - if (!(*m_GlyphItems.Impl())[j].IsInCluster()) + if (!m_GlyphItems[j].IsInCluster()) break; - (*m_GlyphItems.Impl())[j].m_aLinearPos.AdjustX(nDelta + nDiff); + m_GlyphItems[j].m_aLinearPos.AdjustX(nDelta + nDiff); } // If this glyph is Kashida-justifiable, then mark this as a // Kashida position. Since this must be a RTL glyph, we mark the // last glyph in the cluster not the first as this would be the // base glyph. - if (bKashidaJustify && (*m_GlyphItems.Impl())[i].AllowKashida() && - nDiff > (*m_GlyphItems.Impl())[i].charCount()) // Rounding errors, 1 pixel per character! + if (bKashidaJustify && m_GlyphItems[i].AllowKashida() && + nDiff > m_GlyphItems[i].charCount()) // Rounding errors, 1 pixel per character! { pKashidas[i] = nDiff; // Move any non-spacing marks attached to this cluster as well. // Looping backward because this is RTL glyph. while (j > 0) { - if (!(*m_GlyphItems.Impl())[j].IsDiacritic()) + if (!m_GlyphItems[j].IsDiacritic()) break; - (*m_GlyphItems.Impl())[j--].m_aLinearPos.AdjustX(nDiff); + m_GlyphItems[j--].m_aLinearPos.AdjustX(nDiff); } } i++; @@ -776,7 +778,7 @@ void GenericSalLayout::ApplyDXArray(const ImplLayoutArgs& rArgs) size_t nInserted = 0; for (auto const& pKashida : pKashidas) { - auto pGlyphIter = m_GlyphItems.Impl()->begin() + nInserted + pKashida.first; + auto pGlyphIter = m_GlyphItems.begin() + nInserted + pKashida.first; // The total Kashida width. DeviceCoordinate nTotalWidth = pKashida.second; @@ -804,7 +806,7 @@ void GenericSalLayout::ApplyDXArray(const ImplLayoutArgs& rArgs) while (nCopies--) { GlyphItem aKashida(nCharPos, 0, nKashidaIndex, aPos, nFlags, nKashidaWidth, 0, &GetFont()); - pGlyphIter = m_GlyphItems.Impl()->insert(pGlyphIter, aKashida); + pGlyphIter = m_GlyphItems.insert(pGlyphIter, aKashida); aPos.AdjustX(nKashidaWidth ); aPos.AdjustX( -nOverlap ); ++pGlyphIter; @@ -815,7 +817,7 @@ void GenericSalLayout::ApplyDXArray(const ImplLayoutArgs& rArgs) bool GenericSalLayout::IsKashidaPosValid(int nCharPos) const { - for (auto pIter = m_GlyphItems.Impl()->begin(); pIter != m_GlyphItems.Impl()->end(); ++pIter) + for (auto pIter = m_GlyphItems.begin(); pIter != m_GlyphItems.end(); ++pIter) { if (pIter->charPos() == nCharPos) { @@ -823,7 +825,7 @@ bool GenericSalLayout::IsKashidaPosValid(int nCharPos) const // changed the text styling in the middle of a word. Since we don’t // do ligatures across layout engine instances, this can’t be a // ligature so it should be fine. - if (pIter == m_GlyphItems.Impl()->begin()) + if (pIter == m_GlyphItems.begin()) return true; // If the character is not supported by this layout, return false @@ -834,7 +836,7 @@ bool GenericSalLayout::IsKashidaPosValid(int nCharPos) const // Search backwards for previous glyph belonging to a different // character. We are looking backwards because we are dealing with // RTL glyphs, which will be in visual order. - for (auto pPrev = pIter - 1; pPrev != m_GlyphItems.Impl()->begin(); --pPrev) + for (auto pPrev = pIter - 1; pPrev != m_GlyphItems.begin(); --pPrev) { if (pPrev->charPos() != nCharPos) { diff --git a/vcl/source/gdi/impglyphitem.cxx b/vcl/source/gdi/impglyphitem.cxx index 4bb53d4a4596..d271032e2ad6 100644 --- a/vcl/source/gdi/impglyphitem.cxx +++ b/vcl/source/gdi/impglyphitem.cxx @@ -23,43 +23,41 @@ #include <unx/freetype_glyphcache.hxx> #endif -SalLayoutGlyphs::SalLayoutGlyphs() - : m_pImpl(nullptr) +SalLayoutGlyphs::~SalLayoutGlyphs() { + for (SalLayoutGlyphsImpl* impl : m_pImpls) + delete impl; } -SalLayoutGlyphs::~SalLayoutGlyphs() { delete m_pImpl; } +SalLayoutGlyphs::SalLayoutGlyphs(SalLayoutGlyphs&& rOther) { std::swap(m_pImpls, rOther.m_pImpls); } -SalLayoutGlyphs::SalLayoutGlyphs(const SalLayoutGlyphs& rOther) -{ - m_pImpl = rOther.m_pImpl ? rOther.m_pImpl->clone(*this) : nullptr; -} - -SalLayoutGlyphs& SalLayoutGlyphs::operator=(const SalLayoutGlyphs& rOther) +SalLayoutGlyphs& SalLayoutGlyphs::operator=(SalLayoutGlyphs&& rOther) { if (this != &rOther) - { - delete m_pImpl; - m_pImpl = rOther.m_pImpl ? rOther.m_pImpl->clone(*this) : nullptr; - } + std::swap(m_pImpls, rOther.m_pImpls); return *this; } -bool SalLayoutGlyphs::IsValid() const { return m_pImpl && m_pImpl->IsValid(); } - -void SalLayoutGlyphs::Invalidate() +bool SalLayoutGlyphs::IsValid() const { - if (m_pImpl) - m_pImpl->Invalidate(); + if (m_pImpls.empty()) + return false; + for (SalLayoutGlyphsImpl* impl : m_pImpls) + if (!impl->IsValid()) + return false; + return true; } -SalLayoutGlyphsImpl* SalLayoutGlyphsImpl::clone(SalLayoutGlyphs& rGlyphs) const +void SalLayoutGlyphs::Invalidate() { - SalLayoutGlyphsImpl* pNew = new SalLayoutGlyphsImpl(rGlyphs, *m_rFontInstance); - *pNew = *this; - return pNew; + // Invalidating is in fact simply clearing. + for (SalLayoutGlyphsImpl* impl : m_pImpls) + delete impl; + m_pImpls.clear(); } +SalLayoutGlyphsImpl* SalLayoutGlyphsImpl::clone() const { return new SalLayoutGlyphsImpl(*this); } + bool SalLayoutGlyphsImpl::IsValid() const { if (!m_rFontInstance.is()) diff --git a/vcl/source/gdi/sallayout.cxx b/vcl/source/gdi/sallayout.cxx index 067672dc5366..cde5cac31730 100644 --- a/vcl/source/gdi/sallayout.cxx +++ b/vcl/source/gdi/sallayout.cxx @@ -647,6 +647,11 @@ bool SalLayout::GetBoundRect(tools::Rectangle& rRect) const return bRet; } +SalLayoutGlyphs SalLayout::GetGlyphs() const +{ + return SalLayoutGlyphs(); // invalid +} + DeviceCoordinate GenericSalLayout::FillDXArray( DeviceCoordinate* pCharWidths ) const { if (pCharWidths) @@ -665,7 +670,7 @@ DeviceCoordinate GenericSalLayout::GetTextWidth() const DeviceCoordinate nMinPos = 0; DeviceCoordinate nMaxPos = 0; - for (auto const& aGlyphItem : *m_GlyphItems.Impl()) + for (auto const& aGlyphItem : m_GlyphItems) { // update the text extent with the glyph extent DeviceCoordinate nXPos = aGlyphItem.m_aLinearPos.getX(); @@ -692,13 +697,13 @@ void GenericSalLayout::Justify( DeviceCoordinate nNewWidth ) return; } // find rightmost glyph, it won't get stretched - std::vector<GlyphItem>::iterator pGlyphIterRight = m_GlyphItems.Impl()->begin(); - pGlyphIterRight += m_GlyphItems.Impl()->size() - 1; + std::vector<GlyphItem>::iterator pGlyphIterRight = m_GlyphItems.begin(); + pGlyphIterRight += m_GlyphItems.size() - 1; std::vector<GlyphItem>::iterator pGlyphIter; // count stretchable glyphs int nStretchable = 0; int nMaxGlyphWidth = 0; - for(pGlyphIter = m_GlyphItems.Impl()->begin(); pGlyphIter != pGlyphIterRight; ++pGlyphIter) + for(pGlyphIter = m_GlyphItems.begin(); pGlyphIter != pGlyphIterRight; ++pGlyphIter) { if( !pGlyphIter->IsDiacritic() ) ++nStretchable; @@ -721,7 +726,7 @@ void GenericSalLayout::Justify( DeviceCoordinate nNewWidth ) { // expand width by distributing space between glyphs evenly int nDeltaSum = 0; - for( pGlyphIter = m_GlyphItems.Impl()->begin(); pGlyphIter != pGlyphIterRight; ++pGlyphIter ) + for( pGlyphIter = m_GlyphItems.begin(); pGlyphIter != pGlyphIterRight; ++pGlyphIter ) { // move glyph to justified position pGlyphIter->m_aLinearPos.AdjustX(nDeltaSum ); @@ -741,9 +746,9 @@ void GenericSalLayout::Justify( DeviceCoordinate nNewWidth ) { // squeeze width by moving glyphs proportionally double fSqueeze = static_cast<double>(nNewWidth) / nOldWidth; - if(m_GlyphItems.Impl()->size() > 1) + if(m_GlyphItems.size() > 1) { - for( pGlyphIter = m_GlyphItems.Impl()->begin(); ++pGlyphIter != pGlyphIterRight;) + for( pGlyphIter = m_GlyphItems.begin(); ++pGlyphIter != pGlyphIterRight;) { int nX = pGlyphIter->m_aLinearPos.getX(); nX = static_cast<int>(nX * fSqueeze); @@ -751,7 +756,7 @@ void GenericSalLayout::Justify( DeviceCoordinate nNewWidth ) } } // adjust glyph widths to new positions - for( pGlyphIter = m_GlyphItems.Impl()->begin(); pGlyphIter != pGlyphIterRight; ++pGlyphIter ) + for( pGlyphIter = m_GlyphItems.begin(); pGlyphIter != pGlyphIterRight; ++pGlyphIter ) pGlyphIter->m_nNewWidth = pGlyphIter[1].m_aLinearPos.getX() - pGlyphIter[0].m_aLinearPos.getX(); } } @@ -804,8 +809,8 @@ void GenericSalLayout::ApplyAsianKerning(const OUString& rStr) const int nLength = rStr.getLength(); tools::Long nOffset = 0; - for (std::vector<GlyphItem>::iterator pGlyphIter = m_GlyphItems.Impl()->begin(), - pGlyphIterEnd = m_GlyphItems.Impl()->end(); + for (std::vector<GlyphItem>::iterator pGlyphIter = m_GlyphItems.begin(), + pGlyphIterEnd = m_GlyphItems.end(); pGlyphIter != pGlyphIterEnd; ++pGlyphIter) { const int n = pGlyphIter->charPos(); @@ -851,7 +856,7 @@ void GenericSalLayout::GetCaretPositions( int nMaxIndex, tools::Long* pCaretXArr pCaretXArray[i] = -1; // calculate caret positions using glyph array - for (auto const& aGlyphItem : *m_GlyphItems.Impl()) + for (auto const& aGlyphItem : m_GlyphItems) { tools::Long nXPos = aGlyphItem.m_aLinearPos.getX(); tools::Long nXRight = nXPos + aGlyphItem.origWidth(); @@ -897,8 +902,8 @@ bool GenericSalLayout::GetNextGlyph(const GlyphItem** pGlyph, Point& rPos, int& nStart, const PhysicalFontFace**) const { - std::vector<GlyphItem>::const_iterator pGlyphIter = m_GlyphItems.Impl()->begin(); - std::vector<GlyphItem>::const_iterator pGlyphIterEnd = m_GlyphItems.Impl()->end(); + std::vector<GlyphItem>::const_iterator pGlyphIter = m_GlyphItems.begin(); + std::vector<GlyphItem>::const_iterator pGlyphIterEnd = m_GlyphItems.end(); pGlyphIter += nStart; // find next glyph in substring @@ -910,7 +915,7 @@ bool GenericSalLayout::GetNextGlyph(const GlyphItem** pGlyph, } // return zero if no more glyph found - if( nStart >= static_cast<int>(m_GlyphItems.Impl()->size()) ) + if( nStart >= static_cast<int>(m_GlyphItems.size()) ) return false; if( pGlyphIter == pGlyphIterEnd ) @@ -932,10 +937,10 @@ bool GenericSalLayout::GetNextGlyph(const GlyphItem** pGlyph, void GenericSalLayout::MoveGlyph( int nStart, tools::Long nNewXPos ) { - if( nStart >= static_cast<int>(m_GlyphItems.Impl()->size()) ) + if( nStart >= static_cast<int>(m_GlyphItems.size()) ) return; - std::vector<GlyphItem>::iterator pGlyphIter = m_GlyphItems.Impl()->begin(); + std::vector<GlyphItem>::iterator pGlyphIter = m_GlyphItems.begin(); pGlyphIter += nStart; // the nNewXPos argument determines the new cell position @@ -948,7 +953,7 @@ void GenericSalLayout::MoveGlyph( int nStart, tools::Long nNewXPos ) // adjust all following glyph positions if needed if( nXDelta != 0 ) { - for( std::vector<GlyphItem>::iterator pGlyphIterEnd = m_GlyphItems.Impl()->end(); pGlyphIter != pGlyphIterEnd; ++pGlyphIter ) + for( std::vector<GlyphItem>::iterator pGlyphIterEnd = m_GlyphItems.end(); pGlyphIter != pGlyphIterEnd; ++pGlyphIter ) { pGlyphIter->m_aLinearPos.AdjustX(nXDelta ); } @@ -957,10 +962,10 @@ void GenericSalLayout::MoveGlyph( int nStart, tools::Long nNewXPos ) void GenericSalLayout::DropGlyph( int nStart ) { - if( nStart >= static_cast<int>(m_GlyphItems.Impl()->size())) + if( nStart >= static_cast<int>(m_GlyphItems.size())) return; - std::vector<GlyphItem>::iterator pGlyphIter = m_GlyphItems.Impl()->begin(); + std::vector<GlyphItem>::iterator pGlyphIter = m_GlyphItems.begin(); pGlyphIter += nStart; pGlyphIter->dropGlyph(); } @@ -969,20 +974,20 @@ void GenericSalLayout::Simplify( bool bIsBase ) { // remove dropped glyphs inplace size_t j = 0; - for(size_t i = 0; i < m_GlyphItems.Impl()->size(); i++ ) + for(size_t i = 0; i < m_GlyphItems.size(); i++ ) { - if (bIsBase && (*m_GlyphItems.Impl())[i].IsDropped()) + if (bIsBase && m_GlyphItems[i].IsDropped()) continue; - if (!bIsBase && (*m_GlyphItems.Impl())[i].glyphId() == 0) + if (!bIsBase && m_GlyphItems[i].glyphId() == 0) continue; if( i != j ) { - (*m_GlyphItems.Impl())[j] = (*m_GlyphItems.Impl())[i]; + m_GlyphItems[j] = m_GlyphItems[i]; } j += 1; } - m_GlyphItems.Impl()->erase(m_GlyphItems.Impl()->begin() + j, m_GlyphItems.Impl()->end()); + m_GlyphItems.erase(m_GlyphItems.begin() + j, m_GlyphItems.end()); } MultiSalLayout::MultiSalLayout( std::unique_ptr<SalLayout> pBaseLayout ) @@ -1023,7 +1028,7 @@ void MultiSalLayout::AddFallback( std::unique_ptr<SalLayout> pFallback, ++mnLevel; } -bool MultiSalLayout::LayoutText( ImplLayoutArgs& rArgs, const SalLayoutGlyphs* ) +bool MultiSalLayout::LayoutText( ImplLayoutArgs& rArgs, const SalLayoutGlyphsImpl* ) { if( mnLevel <= 1 ) return false; @@ -1576,10 +1581,13 @@ bool MultiSalLayout::IsKashidaPosValid(int nCharPos) const return bValid; } -const SalLayoutGlyphs* SalLayout::GetGlyphs() const +SalLayoutGlyphs MultiSalLayout::GetGlyphs() const { - // No access to the glyphs by default. - return nullptr; + SalLayoutGlyphs glyphs; + for( int n = 0; n < mnLevel; ++n ) + glyphs.AppendImpl(mpLayouts[n]->GlyphsImpl().clone()); + return glyphs; } + /* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/vcl/source/outdev/font.cxx b/vcl/source/outdev/font.cxx index 2cd38a58ba11..0c6c29674527 100644 --- a/vcl/source/outdev/font.cxx +++ b/vcl/source/outdev/font.cxx @@ -1210,7 +1210,7 @@ void OutputDevice::ImplDrawEmphasisMarks( SalLayout& rSalLayout ) std::unique_ptr<SalLayout> OutputDevice::getFallbackLayout( LogicalFontInstance* pLogicalFont, int nFallbackLevel, - ImplLayoutArgs& rLayoutArgs) const + ImplLayoutArgs& rLayoutArgs, const SalLayoutGlyphs* pGlyphs) const { // we need a graphics if (!mpGraphics && !AcquireGraphics()) @@ -1225,7 +1225,7 @@ std::unique_ptr<SalLayout> OutputDevice::getFallbackLayout( if (!pFallback) return nullptr; - if (!pFallback->LayoutText(rLayoutArgs, nullptr)) + if (!pFallback->LayoutText(rLayoutArgs, pGlyphs ? pGlyphs->Impl(nFallbackLevel) : nullptr)) { // there is no need for a font that couldn't resolve anything return nullptr; @@ -1234,7 +1234,8 @@ std::unique_ptr<SalLayout> OutputDevice::getFallbackLayout( return pFallback; } -std::unique_ptr<SalLayout> OutputDevice::ImplGlyphFallbackLayout( std::unique_ptr<SalLayout> pSalLayout, ImplLayoutArgs& rLayoutArgs ) const +std::unique_ptr<SalLayout> OutputDevice::ImplGlyphFallbackLayout( std::unique_ptr<SalLayout> pSalLayout, + ImplLayoutArgs& rLayoutArgs, const SalLayoutGlyphs* pGlyphs ) const { // This function relies on a valid mpFontInstance, if it doesn't exist bail out // - we'd have crashed later on anyway. At least here we can catch the error in debug @@ -1288,7 +1289,7 @@ std::unique_ptr<SalLayout> OutputDevice::ImplGlyphFallbackLayout( std::unique_pt // create and add glyph fallback layout to multilayout std::unique_ptr<SalLayout> pFallback = getFallbackLayout(pFallbackFont.get(), - nFallbackLevel, rLayoutArgs); + nFallbackLevel, rLayoutArgs, pGlyphs); if (pFallback) { if( !pMultiSalLayout ) diff --git a/vcl/source/outdev/text.cxx b/vcl/source/outdev/text.cxx index 8b8c5363a2cc..1b8d021d0fe1 100644 --- a/vcl/source/outdev/text.cxx +++ b/vcl/source/outdev/text.cxx @@ -1317,7 +1317,7 @@ std::unique_ptr<SalLayout> OutputDevice::ImplLayout(const OUString& rOrigStr, std::unique_ptr<SalLayout> pSalLayout = mpGraphics->GetTextLayout(0); // layout text - if( pSalLayout && !pSalLayout->LayoutText( aLayoutArgs, pGlyphs ) ) + if( pSalLayout && !pSalLayout->LayoutText( aLayoutArgs, pGlyphs ? pGlyphs->Impl(0) : nullptr ) ) { pSalLayout.reset(); } @@ -1328,7 +1328,7 @@ std::unique_ptr<SalLayout> OutputDevice::ImplLayout(const OUString& rOrigStr, // do glyph fallback if needed // #105768# avoid fallback for very small font sizes if (aLayoutArgs.NeedFallback() && mpFontInstance->GetFontSelectPattern().mnHeight >= 3) - pSalLayout = ImplGlyphFallbackLayout(std::move(pSalLayout), aLayoutArgs); + pSalLayout = ImplGlyphFallbackLayout(std::move(pSalLayout), aLayoutArgs, pGlyphs); if (flags & SalLayoutFlags::GlyphItemsOnly) // Return glyph items only after fallback handling. Otherwise they may diff --git a/vcl/source/window/menuitemlist.cxx b/vcl/source/window/menuitemlist.cxx index 6921e6208118..a9903447c748 100644 --- a/vcl/source/window/menuitemlist.cxx +++ b/vcl/source/window/menuitemlist.cxx @@ -52,12 +52,8 @@ SalLayoutGlyphs* MenuItemData::GetTextGlyphs(const OutputDevice* pOutputDevice) if (!pLayout) return nullptr; - const SalLayoutGlyphs* pGlyphs = pLayout->GetGlyphs(); - if (!pGlyphs) - return nullptr; - // Remember the calculation result. - aTextGlyphs = *pGlyphs; + aTextGlyphs = pLayout->GetGlyphs(); return &aTextGlyphs; } diff --git a/vcl/source/window/status.cxx b/vcl/source/window/status.cxx index e24a76da30c1..e3c193609bd3 100644 --- a/vcl/source/window/status.cxx +++ b/vcl/source/window/status.cxx @@ -398,8 +398,8 @@ void StatusBar::ImplDrawItem(vcl::RenderContext& rRenderContext, bool bOffScreen pLayoutCache = pItem->mxLayoutCache.get(); } - const SalLayoutGlyphs* pGlyphs = pLayoutCache ? pLayoutCache->GetGlyphs() : nullptr; - Size aTextSize(rRenderContext.GetTextWidth(pItem->maText,0,-1,nullptr,pGlyphs), rRenderContext.GetTextHeight()); + const SalLayoutGlyphs glyphs = pLayoutCache ? pLayoutCache->GetGlyphs() : SalLayoutGlyphs(); + Size aTextSize(rRenderContext.GetTextWidth(pItem->maText,0,-1,nullptr,&glyphs), rRenderContext.GetTextHeight()); Point aTextPos = ImplGetItemTextPos(aTextRectSize, aTextSize, pItem->mnBits); if (bOffScreen) @@ -408,7 +408,7 @@ void StatusBar::ImplDrawItem(vcl::RenderContext& rRenderContext, bool bOffScreen aTextPos, pItem->maText, 0, -1, nullptr, nullptr, - pGlyphs ); + &glyphs ); } else { @@ -418,7 +418,7 @@ void StatusBar::ImplDrawItem(vcl::RenderContext& rRenderContext, bool bOffScreen aTextPos, pItem->maText, 0, -1, nullptr, nullptr, - pGlyphs ); + &glyphs ); } } @@ -1139,15 +1139,15 @@ void StatusBar::SetItemText( sal_uInt16 nItemId, const OUString& rText, int nCha if (nCharsWidth != -1) { std::unique_ptr<SalLayout> pSalLayout = ImplLayout("0",0,-1); - const SalLayoutGlyphs* pGlyphs = pSalLayout ? pSalLayout->GetGlyphs() : nullptr; - nWidth = GetTextWidth("0",0,-1,nullptr,pGlyphs ); + const SalLayoutGlyphs glyphs = pSalLayout ? pSalLayout->GetGlyphs() : SalLayoutGlyphs(); + nWidth = GetTextWidth("0",0,-1,nullptr,&glyphs); nWidth = nWidth * nCharsWidth + nFudge; } else { std::unique_ptr<SalLayout> pSalLayout = ImplLayout(pItem->maText,0,-1); - const SalLayoutGlyphs* pGlyphs = pSalLayout ? pSalLayout->GetGlyphs() : nullptr; - nWidth = GetTextWidth( pItem->maText,0,-1,nullptr,pGlyphs ) + nFudge; + const SalLayoutGlyphs glyphs = pSalLayout ? pSalLayout->GetGlyphs() : SalLayoutGlyphs(); + nWidth = GetTextWidth( pItem->maText,0,-1,nullptr,&glyphs) + nFudge; // Store the calculated layout. pItem->mxLayoutCache = std::move(pSalLayout); } _______________________________________________ Libreoffice-commits mailing list libreoffice-comm...@lists.freedesktop.org https://lists.freedesktop.org/mailman/listinfo/libreoffice-commits