diff options
-rw-r--r-- | include/vcl/outdev.hxx | 20 | ||||
-rw-r--r-- | sw/source/core/inc/drawfont.hxx | 16 | ||||
-rw-r--r-- | sw/source/core/text/guess.cxx | 7 | ||||
-rw-r--r-- | sw/source/core/text/inftxt.cxx | 35 | ||||
-rw-r--r-- | sw/source/core/text/inftxt.hxx | 25 | ||||
-rw-r--r-- | sw/source/core/text/porfld.cxx | 4 | ||||
-rw-r--r-- | sw/source/core/text/pormulti.cxx | 3 | ||||
-rw-r--r-- | sw/source/core/txtnode/fntcache.cxx | 7 | ||||
-rw-r--r-- | vcl/generic/glyphs/gcach_layout.cxx | 64 | ||||
-rw-r--r-- | vcl/inc/generic/glyphcache.hxx | 3 | ||||
-rw-r--r-- | vcl/inc/sallayout.hxx | 12 | ||||
-rw-r--r-- | vcl/source/gdi/sallayout.cxx | 10 | ||||
-rw-r--r-- | vcl/source/outdev/text.cxx | 53 |
13 files changed, 213 insertions, 46 deletions
diff --git a/include/vcl/outdev.hxx b/include/vcl/outdev.hxx index 7911b662b285..47c77ad4c47c 100644 --- a/include/vcl/outdev.hxx +++ b/include/vcl/outdev.hxx @@ -140,6 +140,7 @@ namespace vcl class ExtOutDevData; class ITextLayout; struct FontCapabilities; + class TextLayoutCache; } // OutputDevice-Types @@ -1066,7 +1067,8 @@ public: See also GetTextBoundRect() for more explanation + code examples. */ - long GetTextWidth( const OUString& rStr, sal_Int32 nIndex = 0, sal_Int32 nLen = -1 ) const; + long GetTextWidth( const OUString& rStr, sal_Int32 nIndex = 0, sal_Int32 nLen = -1, + vcl::TextLayoutCache const* = nullptr) const; /** Height where any character of the current font fits; in logic coordinates. @@ -1081,7 +1083,8 @@ public: sal_Int32 nLen = -1, int flags = 0); long GetTextArray( const OUString& rStr, long* pDXAry = NULL, - sal_Int32 nIndex = 0, sal_Int32 nLen = -1 ) const; + sal_Int32 nIndex = 0, sal_Int32 nLen = -1, + vcl::TextLayoutCache const* = nullptr) const; bool GetCaretPositions( const OUString&, long* pCaretXArray, sal_Int32 nIndex, sal_Int32 nLen, @@ -1092,11 +1095,14 @@ public: sal_Int32 nIndex = 0, sal_Int32 nLen = -1); sal_Int32 GetTextBreak( const OUString& rStr, long nTextWidth, sal_Int32 nIndex = 0, sal_Int32 nLen = -1, - long nCharExtra = 0 ) const; + long nCharExtra = 0, + vcl::TextLayoutCache const* = nullptr) const; sal_Int32 GetTextBreak( const OUString& rStr, long nTextWidth, sal_Unicode nExtraChar, sal_Int32& rExtraCharPos, sal_Int32 nIndex, sal_Int32 nLen, - long nCharExtra = 0 ) const; + long nCharExtra = 0, + vcl::TextLayoutCache const* = nullptr) const; + std::shared_ptr<vcl::TextLayoutCache> CreateTextLayoutCache(OUString const&) const; private: SAL_DLLPRIVATE void ImplInitTextColor(); @@ -1247,9 +1253,11 @@ public: virtual bool HasMirroredGraphics() const; SAL_DLLPRIVATE SalLayout* ImplLayout( const OUString&, sal_Int32 nIndex, sal_Int32 nLen, const Point& rLogicPos = Point(0,0), long nLogicWidth=0, - const long* pLogicDXArray=NULL, int flags=0 ) const; + const long* pLogicDXArray=NULL, int flags=0, + vcl::TextLayoutCache const* = nullptr) const; SAL_DLLPRIVATE ImplLayoutArgs ImplPrepareLayoutArgs( OUString&, const sal_Int32 nIndex, const sal_Int32 nLen, - DeviceCoordinate nPixelWidth, const DeviceCoordinate* pPixelDXArray, int flags = 0 ) const; + DeviceCoordinate nPixelWidth, const DeviceCoordinate* pPixelDXArray, int flags = 0, + vcl::TextLayoutCache const* = nullptr) const; SAL_DLLPRIVATE SalLayout* ImplGlyphFallbackLayout( SalLayout*, ImplLayoutArgs& ) const; // tells whether this output device is RTL in an LTR UI or LTR in a RTL UI SAL_DLLPRIVATE SalLayout* getFallbackFont(ImplFontEntry &rFallbackFont, diff --git a/sw/source/core/inc/drawfont.hxx b/sw/source/core/inc/drawfont.hxx index 033d4901b263..fee34b12737e 100644 --- a/sw/source/core/inc/drawfont.hxx +++ b/sw/source/core/inc/drawfont.hxx @@ -31,7 +31,10 @@ class Point; class SwWrongList; class Size; class SwFont; -namespace vcl { class Font; } +namespace vcl { + class Font; + class TextLayoutCache; +} class SwUnderlineFont; // encapsulates information for drawing text @@ -42,6 +45,7 @@ class SwDrawTextInfo SwViewShell const * pSh; const SwScriptInfo* pScriptInfo; Point m_aPos; + vcl::TextLayoutCache const* m_pCachedVclData; OUString m_aText; const SwWrongList* pWrong; const SwWrongList* pGrammarCheck; @@ -104,7 +108,9 @@ public: SwDrawTextInfo( SwViewShell const *pS, OutputDevice &rO, const SwScriptInfo* pSI, const OUString &rSt, sal_Int32 nI, sal_Int32 nL, - sal_uInt16 nW = 0, bool bB = false ) + sal_uInt16 nW = 0, bool bB = false, + vcl::TextLayoutCache const*const pCachedVclData = nullptr) + : m_pCachedVclData(pCachedVclData) { pFrm = NULL; pSh = pS; @@ -200,6 +206,11 @@ public: return pHyphPos; } + vcl::TextLayoutCache const* GetVclCache() const + { + return m_pCachedVclData; + } + const OUString &GetText() const { return m_aText; @@ -416,6 +427,7 @@ public: void SetText( const OUString &rNew ) { m_aText = rNew; + m_pCachedVclData = nullptr; // would any case benefit from save/restore? } void SetWrong( const SwWrongList* pNew ) diff --git a/sw/source/core/text/guess.cxx b/sw/source/core/text/guess.cxx index 03396469609b..b379308e59b0 100644 --- a/sw/source/core/text/guess.cxx +++ b/sw/source/core/text/guess.cxx @@ -152,14 +152,14 @@ bool SwTxtGuess::Guess( const SwTxtPortion& rPor, SwTxtFormatInfo &rInf, // considering an additional "-" for hyphenation if( bHyph ) { - nCutPos = rInf.GetTxtBreak( nLineWidth, nMaxLen, nMaxComp, nHyphPos ); + nCutPos = rInf.GetTxtBreak( nLineWidth, nMaxLen, nMaxComp, nHyphPos, rInf.GetCachedVclData().get() ); if ( !nHyphPos && rInf.GetIdx() ) nHyphPos = rInf.GetIdx() - 1; } else { - nCutPos = rInf.GetTxtBreak( nLineWidth, nMaxLen, nMaxComp ); + nCutPos = rInf.GetTxtBreak( nLineWidth, nMaxLen, nMaxComp, rInf.GetCachedVclData().get() ); #if OSL_DEBUG_LEVEL > 1 if ( COMPLETE_STRING != nCutPos ) @@ -504,7 +504,8 @@ bool SwTxtGuess::Guess( const SwTxtPortion& rPor, SwTxtFormatInfo &rInf, if( nPorLen ) { rInf.GetTxtSize( &rSI, rInf.GetIdx(), nPorLen, - nMaxComp, nBreakWidth, nMaxSizeDiff ); + nMaxComp, nBreakWidth, nMaxSizeDiff, + rInf.GetCachedVclData().get() ); // save maximum width for later use if ( nMaxSizeDiff ) diff --git a/sw/source/core/text/inftxt.cxx b/sw/source/core/text/inftxt.cxx index 6a622e44352d..b738d9f5e17f 100644 --- a/sw/source/core/text/inftxt.cxx +++ b/sw/source/core/text/inftxt.cxx @@ -21,6 +21,7 @@ #include <unotools/linguprops.hxx> #include <unotools/lingucfg.hxx> #include <hintids.hxx> +#include <svl/ctloptions.hxx> #include <sfx2/printer.hxx> #include <editeng/hyphenzoneitem.hxx> #include <editeng/escapementitem.hxx> @@ -360,7 +361,7 @@ SwPosSize SwTxtSizeInfo::GetTxtSize( OutputDevice* pOutDev, const OUString& rTxt, const sal_Int32 nIndex, const sal_Int32 nLength, - const sal_uInt16 nComp ) const + const sal_uInt16 nComp) const { SwDrawTextInfo aDrawInf( m_pVsh, *pOutDev, pSI, rTxt, nIndex, nLength ); aDrawInf.SetFrm( m_pFrm ); @@ -393,9 +394,11 @@ SwPosSize SwTxtSizeInfo::GetTxtSize() const void SwTxtSizeInfo::GetTxtSize( const SwScriptInfo* pSI, const sal_Int32 nIndex, const sal_Int32 nLength, const sal_uInt16 nComp, - sal_uInt16& nMinSize, sal_uInt16& nMaxSizeDiff ) const + sal_uInt16& nMinSize, sal_uInt16& nMaxSizeDiff, + vcl::TextLayoutCache const*const pCache) const { - SwDrawTextInfo aDrawInf( m_pVsh, *m_pOut, pSI, *m_pTxt, nIndex, nLength ); + SwDrawTextInfo aDrawInf( m_pVsh, *m_pOut, pSI, *m_pTxt, nIndex, nLength, + 0, false, pCache); aDrawInf.SetFrm( m_pFrm ); aDrawInf.SetFont( m_pFnt ); aDrawInf.SetSnapToGrid( SnapToGrid() ); @@ -407,14 +410,15 @@ void SwTxtSizeInfo::GetTxtSize( const SwScriptInfo* pSI, const sal_Int32 nIndex, sal_Int32 SwTxtSizeInfo::GetTxtBreak( const long nLineWidth, const sal_Int32 nMaxLen, - const sal_uInt16 nComp ) const + const sal_uInt16 nComp, + vcl::TextLayoutCache const*const pCache) const { const SwScriptInfo& rScriptInfo = const_cast<SwParaPortion*>(GetParaPortion())->GetScriptInfo(); OSL_ENSURE( m_pRef == m_pOut, "GetTxtBreak is supposed to use the RefDev" ); SwDrawTextInfo aDrawInf( m_pVsh, *m_pOut, &rScriptInfo, - *m_pTxt, GetIdx(), nMaxLen ); + *m_pTxt, GetIdx(), nMaxLen, 0, false, pCache ); aDrawInf.SetFrm( m_pFrm ); aDrawInf.SetFont( m_pFnt ); aDrawInf.SetSnapToGrid( SnapToGrid() ); @@ -427,14 +431,15 @@ sal_Int32 SwTxtSizeInfo::GetTxtBreak( const long nLineWidth, sal_Int32 SwTxtSizeInfo::GetTxtBreak( const long nLineWidth, const sal_Int32 nMaxLen, const sal_uInt16 nComp, - sal_Int32& rExtraCharPos ) const + sal_Int32& rExtraCharPos, + vcl::TextLayoutCache const*const pCache) const { const SwScriptInfo& rScriptInfo = const_cast<SwParaPortion*>(GetParaPortion())->GetScriptInfo(); OSL_ENSURE( m_pRef == m_pOut, "GetTxtBreak is supposed to use the RefDev" ); SwDrawTextInfo aDrawInf( m_pVsh, *m_pOut, &rScriptInfo, - *m_pTxt, GetIdx(), nMaxLen ); + *m_pTxt, GetIdx(), nMaxLen, 0, false, pCache ); aDrawInf.SetFrm( m_pFrm ); aDrawInf.SetFont( m_pFnt ); aDrawInf.SetSnapToGrid( SnapToGrid() ); @@ -1339,6 +1344,19 @@ void SwTxtFormatInfo::CtorInitTxtFormatInfo( SwTxtFrm *pNewFrm, const bool bNewI nLineHeight = 0; nLineNetHeight = 0; SetLineStart(0); + + SvtCTLOptions::TextNumerals const nTextNumerals( + SW_MOD()->GetCTLOptions().GetCTLTextNumerals()); + // cannot cache for NUMERALS_CONTEXT because we need to know the string + // for the whole paragraph now + if (nTextNumerals != SvtCTLOptions::NUMERALS_CONTEXT) + { + // set digit mode to what will be used later to get same results + SwDigitModeModifier const m(*m_pRef, LANGUAGE_NONE /*dummy*/); + assert(m_pRef->GetDigitLanguage() != LANGUAGE_NONE); + SetCachedVclData(m_pRef->CreateTextLayoutCache(*m_pTxt)); + } + Init(); } @@ -1642,9 +1660,11 @@ SwTxtSlot::SwTxtSlot( nIdx = pInf->GetIdx(); nLen = pInf->GetLen(); pOldTxt = &(pInf->GetTxt()); + m_pOldCachedVclData = pInf->GetCachedVclData(); pInf->SetTxt( aTxt ); pInf->SetIdx( 0 ); pInf->SetLen( bTxtLen ? pInf->GetTxt().getLength() : pPor->GetLen() ); + pInf->SetCachedVclData(nullptr); // ST2 if ( bExgLists ) @@ -1689,6 +1709,7 @@ SwTxtSlot::~SwTxtSlot() { if( bOn ) { + pInf->SetCachedVclData(m_pOldCachedVclData); pInf->SetTxt( *pOldTxt ); pInf->SetIdx( nIdx ); pInf->SetLen( nLen ); diff --git a/sw/source/core/text/inftxt.hxx b/sw/source/core/text/inftxt.hxx index a0b627c2bf48..45680164e43a 100644 --- a/sw/source/core/text/inftxt.hxx +++ b/sw/source/core/text/inftxt.hxx @@ -158,6 +158,11 @@ protected: OutputDevice* m_pOut; OutputDevice* m_pRef; + // performance hack - this is only used by SwTxtFormatInfo but + // because it's not even possible to dynamic_cast these things + // currently it has to be stored here + std::shared_ptr<vcl::TextLayoutCache> m_pCachedVclData; + SwFont *m_pFnt; SwUnderlineFont *m_pUnderFnt; // Font for underlining SwTxtFrm *m_pFrm; @@ -295,18 +300,21 @@ public: SwPosSize GetTxtSize() const; void GetTxtSize( const SwScriptInfo* pSI, const sal_Int32 nIdx, const sal_Int32 nLen, const sal_uInt16 nComp, - sal_uInt16& nMinSize, sal_uInt16& nMaxSizeDiff ) const; + sal_uInt16& nMinSize, sal_uInt16& nMaxSizeDiff, + vcl::TextLayoutCache const* = nullptr) const; inline SwPosSize GetTxtSize( const SwScriptInfo* pSI, const sal_Int32 nIdx, const sal_Int32 nLen, const sal_uInt16 nComp ) const; inline SwPosSize GetTxtSize( const OUString &rTxt ) const; sal_Int32 GetTxtBreak( const long nLineWidth, const sal_Int32 nMaxLen, - const sal_uInt16 nComp ) const; + const sal_uInt16 nComp, + vcl::TextLayoutCache const* = nullptr) const; sal_Int32 GetTxtBreak( const long nLineWidth, const sal_Int32 nMaxLen, const sal_uInt16 nComp, - sal_Int32& rExtraCharPos ) const; + sal_Int32& rExtraCharPos, + vcl::TextLayoutCache const* = nullptr) const; sal_uInt16 GetAscent() const; @@ -371,6 +379,15 @@ public: { return ( m_pKanaComp && m_nKanaIdx < m_pKanaComp->size() ) ? (*m_pKanaComp)[m_nKanaIdx] : 0; } + std::shared_ptr<vcl::TextLayoutCache> GetCachedVclData() const + { + return m_pCachedVclData; + } + void SetCachedVclData(std::shared_ptr<vcl::TextLayoutCache> const& pCachedVclData) + { + m_pCachedVclData = pCachedVclData; + } + #ifdef DBG_UTIL bool IsOptDbg() const; #endif @@ -725,6 +742,7 @@ public: inline void SetTabOverflow( bool bOverflow ) { bTabOverflow = bOverflow; } inline bool IsTabOverflow() { return bTabOverflow; } + }; /** @@ -737,6 +755,7 @@ public: class SwTxtSlot { OUString aTxt; + std::shared_ptr<vcl::TextLayoutCache> m_pOldCachedVclData; const OUString *pOldTxt; const SwWrongList* pOldSmartTagList; const SwWrongList* pOldGrammarCheckList; diff --git a/sw/source/core/text/porfld.cxx b/sw/source/core/text/porfld.cxx index ae446176bf96..95b1542fe8cc 100644 --- a/sw/source/core/text/porfld.cxx +++ b/sw/source/core/text/porfld.cxx @@ -136,6 +136,7 @@ sal_uInt16 SwFldPortion::GetViewWidth( const SwTxtSizeInfo &rInf ) const */ class SwFldSlot { + std::shared_ptr<vcl::TextLayoutCache> m_pOldCachedVclData; const OUString *pOldTxt; OUString aTxt; sal_Int32 nIdx; @@ -162,7 +163,9 @@ SwFldSlot::SwFldSlot( const SwTxtFormatInfo* pNew, const SwFldPortion *pPor ) nIdx = pInf->GetIdx(); nLen = pInf->GetLen(); pOldTxt = &(pInf->GetTxt()); + m_pOldCachedVclData = pInf->GetCachedVclData(); pInf->SetLen( aTxt.getLength() ); + pInf->SetCachedVclData(nullptr); if( pPor->IsFollow() ) { pInf->SetFakeLineStart( nIdx > pInf->GetLineStart() ); @@ -180,6 +183,7 @@ SwFldSlot::~SwFldSlot() { if( bOn ) { + pInf->SetCachedVclData(m_pOldCachedVclData); pInf->SetTxt( *pOldTxt ); pInf->SetIdx( nIdx ); pInf->SetLen( nLen ); diff --git a/sw/source/core/text/pormulti.cxx b/sw/source/core/text/pormulti.cxx index 9df8de427167..2bb8217403fa 100644 --- a/sw/source/core/text/pormulti.cxx +++ b/sw/source/core/text/pormulti.cxx @@ -1735,6 +1735,8 @@ bool SwTxtFormatter::BuildMultiPortion( SwTxtFormatInfo &rInf, // save some values const OUString* pOldTxt = &(rInf.GetTxt()); const SwTwips nOldPaintOfst = rInf.GetPaintOfst(); + std::shared_ptr<vcl::TextLayoutCache> const pOldCachedVclData(rInf.GetCachedVclData()); + rInf.SetCachedVclData(nullptr); OUString const aMultiStr( rInf.GetTxt().copy(0, nMultiLen + rInf.GetIdx()) ); rInf.SetTxt( aMultiStr ); @@ -2053,6 +2055,7 @@ bool SwTxtFormatter::BuildMultiPortion( SwTxtFormatInfo &rInf, rInf.SetRest( pTmp ); } + rInf.SetCachedVclData(pOldCachedVclData); rInf.SetTxt( *pOldTxt ); rInf.SetPaintOfst( nOldPaintOfst ); rInf.SetStop( aInf.IsStop() ); diff --git a/sw/source/core/txtnode/fntcache.cxx b/sw/source/core/txtnode/fntcache.cxx index 7a837ed5945f..9ba646dcd282 100644 --- a/sw/source/core/txtnode/fntcache.cxx +++ b/sw/source/core/txtnode/fntcache.cxx @@ -1973,7 +1973,8 @@ Size SwFntObj::GetTextSize( SwDrawTextInfo& rInf ) else { aTxtSize.Width() = rInf.GetOut().GetTextWidth( rInf.GetText(), - rInf.GetIdx(), nLn ); + rInf.GetIdx(), nLn, + rInf.GetVclCache()); rInf.SetKanaDiff( 0 ); } @@ -2430,12 +2431,12 @@ sal_Int32 SwFont::GetTxtBreak( SwDrawTextInfo& rInf, long nTextWidth ) sal_Int32 nHyphPos = *rInf.GetHyphPos(); nTxtBreak = rInf.GetOut().GetTextBreak( *pTmpText, nTextWidth, static_cast<sal_Unicode>('-'), nHyphPos, - nTmpIdx, nTmpLen, nKern ); + nTmpIdx, nTmpLen, nKern, rInf.GetVclCache()); *rInf.GetHyphPos() = (nHyphPos == -1) ? COMPLETE_STRING : nHyphPos; } else nTxtBreak = rInf.GetOut().GetTextBreak( *pTmpText, nTextWidth, - nTmpIdx, nTmpLen, nKern ); + nTmpIdx, nTmpLen, nKern, rInf.GetVclCache()); if ( bTextReplaced && nTxtBreak != -1 ) { diff --git a/vcl/generic/glyphs/gcach_layout.cxx b/vcl/generic/glyphs/gcach_layout.cxx index 5010423c03be..8e9deeb4f226 100644 --- a/vcl/generic/glyphs/gcach_layout.cxx +++ b/vcl/generic/glyphs/gcach_layout.cxx @@ -349,6 +349,41 @@ struct HbScriptRun typedef std::vector<HbScriptRun> HbScriptRuns; +namespace vcl { + struct Run + { + int32_t nStart; + int32_t nEnd; + UScriptCode nCode; + Run(int32_t nStart_, int32_t nEnd_, UScriptCode nCode_) + : nStart(nStart_), nEnd(nEnd_), nCode(nCode_) + {} + }; + + class TextLayoutCache + { + public: + std::vector<vcl::Run> runs; + TextLayoutCache(OUString const& rString, sal_Int32 const nEnd) + { + vcl::ScriptRun aScriptRun( + reinterpret_cast<const UChar *>(rString.getStr()), + nEnd); + while (aScriptRun.next()) + { + runs.push_back(Run(aScriptRun.getScriptStart(), + aScriptRun.getScriptEnd(), aScriptRun.getScriptCode())); + } + } + }; +} + +std::shared_ptr<vcl::TextLayoutCache> ServerFontLayout::CreateTextLayoutCache( + OUString const& rString) const +{ + return std::make_shared<vcl::TextLayoutCache>(rString, rString.getLength()); +} + bool HbLayoutEngine::Layout(ServerFontLayout& rLayout, ImplLayoutArgs& rArgs) { ServerFont& rFont = rLayout.GetServerFont(); @@ -370,7 +405,18 @@ bool HbLayoutEngine::Layout(ServerFontLayout& rLayout, ImplLayoutArgs& rArgs) rLayout.Reserve(nGlyphCapacity); - vcl::ScriptRun aScriptRun(reinterpret_cast<const UChar *>(rArgs.mpStr), rArgs.mnEndCharPos); + std::unique_ptr<vcl::TextLayoutCache> pNewScriptRun; + vcl::TextLayoutCache const* pTextLayout; + if (rArgs.m_pTextLayoutCache) + { + pTextLayout = rArgs.m_pTextLayoutCache; // use cache! + } + else + { + pNewScriptRun.reset(new vcl::TextLayoutCache( + reinterpret_cast<const UChar *>(rArgs.mpStr), rArgs.mnEndCharPos)); + pTextLayout = pNewScriptRun.get(); + } Point aCurrPos(0, 0); while (true) @@ -383,21 +429,25 @@ bool HbLayoutEngine::Layout(ServerFontLayout& rLayout, ImplLayoutArgs& rArgs) // Find script subruns. int nCurrentPos = nBidiMinRunPos; HbScriptRuns aScriptSubRuns; - while (aScriptRun.next()) + size_t k = 0; + for (; k < pTextLayout->runs.size(); ++k) { - if (aScriptRun.getScriptStart() <= nCurrentPos && aScriptRun.getScriptEnd() > nCurrentPos) + vcl::Run const& rRun(pTextLayout->runs[k]); + if (rRun.nStart <= nCurrentPos && nCurrentPos < rRun.nEnd) + { break; + } } while (nCurrentPos < nBidiEndRunPos) { int32_t nMinRunPos = nCurrentPos; - int32_t nEndRunPos = std::min(aScriptRun.getScriptEnd(), nBidiEndRunPos); - HbScriptRun aRun(nMinRunPos, nEndRunPos, aScriptRun.getScriptCode()); + int32_t nEndRunPos = std::min(pTextLayout->runs[k].nEnd, nBidiEndRunPos); + HbScriptRun aRun(nMinRunPos, nEndRunPos, pTextLayout->runs[k].nCode); aScriptSubRuns.push_back(aRun); nCurrentPos = nEndRunPos; - aScriptRun.next(); + ++k; } // RTL subruns should be reversed to ensure that final glyph order is @@ -405,8 +455,6 @@ bool HbLayoutEngine::Layout(ServerFontLayout& rLayout, ImplLayoutArgs& rArgs) if (bRightToLeft) std::reverse(aScriptSubRuns.begin(), aScriptSubRuns.end()); - aScriptRun.reset(); - for (HbScriptRuns::iterator it = aScriptSubRuns.begin(); it != aScriptSubRuns.end(); ++it) { int nMinRunPos = it->mnMin; diff --git a/vcl/inc/generic/glyphcache.hxx b/vcl/inc/generic/glyphcache.hxx index c8d3552ba7c9..ae9e30b9c59a 100644 --- a/vcl/inc/generic/glyphcache.hxx +++ b/vcl/inc/generic/glyphcache.hxx @@ -299,6 +299,9 @@ public: ServerFont& GetServerFont() const { return mrServerFont; } + virtual std::shared_ptr<vcl::TextLayoutCache> + CreateTextLayoutCache(OUString const&) const SAL_OVERRIDE; + private: ServerFont& mrServerFont; com::sun::star::uno::Reference<com::sun::star::i18n::XBreakIterator> mxBreak; diff --git a/vcl/inc/sallayout.hxx b/vcl/inc/sallayout.hxx index 943f8eb6bf5b..7ad886640d5c 100644 --- a/vcl/inc/sallayout.hxx +++ b/vcl/inc/sallayout.hxx @@ -41,6 +41,9 @@ typedef unsigned short LanguageType; class SalGraphics; class PhysicalFontFace; +namespace vcl { + class TextLayoutCache; +} // used for managing runs e.g. for BiDi, glyph and script fallback class VCL_PLUGIN_PUBLIC ImplLayoutRuns @@ -76,6 +79,9 @@ public: int mnEndCharPos; const sal_Unicode* mpStr; + // performance hack + vcl::TextLayoutCache const* m_pTextLayoutCache; + // positioning related inputs const DeviceCoordinate* mpDXArray; // in pixel units DeviceCoordinate mnLayoutWidth; // in pixel units @@ -88,7 +94,8 @@ public: public: ImplLayoutArgs( const sal_Unicode* pStr, int nLength, int nMinCharPos, int nEndCharPos, int nFlags, - const LanguageTag& rLanguageTag ); + const LanguageTag& rLanguageTag, + vcl::TextLayoutCache const* pLayoutCache); void SetLayoutWidth( DeviceCoordinate nWidth ) { mnLayoutWidth = nWidth; } void SetDXArray( const DeviceCoordinate* pDXArray ) { mpDXArray = pDXArray; } @@ -194,6 +201,9 @@ public: virtual void Simplify( bool bIsBase ) = 0; virtual void DisableGlyphInjection( bool /*bDisable*/ ) {} + virtual std::shared_ptr<vcl::TextLayoutCache> + CreateTextLayoutCache(OUString const&) const; + protected: // used by layout engines SalLayout(); diff --git a/vcl/source/gdi/sallayout.cxx b/vcl/source/gdi/sallayout.cxx index 9ba3dcc21d02..c6897f20c76f 100644 --- a/vcl/source/gdi/sallayout.cxx +++ b/vcl/source/gdi/sallayout.cxx @@ -486,7 +486,8 @@ bool ImplLayoutRuns::GetRun( int* nMinRunPos, int* nEndRunPos, bool* bRightToLef } ImplLayoutArgs::ImplLayoutArgs( const sal_Unicode* pStr, int nLen, - int nMinCharPos, int nEndCharPos, int nFlags, const LanguageTag& rLanguageTag ) + int nMinCharPos, int nEndCharPos, int nFlags, const LanguageTag& rLanguageTag, + vcl::TextLayoutCache const*const pLayoutCache) : maLanguageTag( rLanguageTag ), mnFlags( nFlags ), @@ -494,6 +495,7 @@ ImplLayoutArgs::ImplLayoutArgs( const sal_Unicode* pStr, int nLen, mnMinCharPos( nMinCharPos ), mnEndCharPos( nEndCharPos ), mpStr( pStr ), + m_pTextLayoutCache(pLayoutCache), mpDXArray( NULL ), mnLayoutWidth( 0 ), mnOrientation( 0 ) @@ -2128,4 +2130,10 @@ bool MultiSalLayout::GetOutline( SalGraphics& rGraphics, return bRet; } +std::shared_ptr<vcl::TextLayoutCache> SalLayout::CreateTextLayoutCache( + OUString const&) const +{ + return 0; // by default, nothing to cache +} + /* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/vcl/source/outdev/text.cxx b/vcl/source/outdev/text.cxx index 9b97d1de1928..6dfe1098e5c2 100644 --- a/vcl/source/outdev/text.cxx +++ b/vcl/source/outdev/text.cxx @@ -925,10 +925,11 @@ void OutputDevice::DrawText( const Point& rStartPt, const OUString& rStr, mpAlphaVDev->DrawText( rStartPt, rStr, nIndex, nLen, pVector, pDisplayText ); } -long OutputDevice::GetTextWidth( const OUString& rStr, sal_Int32 nIndex, sal_Int32 nLen ) const +long OutputDevice::GetTextWidth( const OUString& rStr, sal_Int32 nIndex, sal_Int32 nLen, + vcl::TextLayoutCache const*const pLayoutCache) const { - long nWidth = GetTextArray( rStr, NULL, nIndex, nLen ); + long nWidth = GetTextArray( rStr, NULL, nIndex, nLen, pLayoutCache ); return nWidth; } @@ -993,7 +994,8 @@ void OutputDevice::DrawTextArray( const Point& rStartPt, const OUString& rStr, } long OutputDevice::GetTextArray( const OUString& rStr, long* pDXAry, - sal_Int32 nIndex, sal_Int32 nLen ) const + sal_Int32 nIndex, sal_Int32 nLen, + vcl::TextLayoutCache const*const pLayoutCache) const { if(nLen == 0x0FFFF) { @@ -1009,7 +1011,8 @@ long OutputDevice::GetTextArray( const OUString& rStr, long* pDXAry, nLen = rStr.getLength() - nIndex; } // do layout - SalLayout* pSalLayout = ImplLayout( rStr, nIndex, nLen ); + SalLayout *const pSalLayout = ImplLayout(rStr, nIndex, nLen, + Point(0,0), 0, nullptr, 0, pLayoutCache); if( !pSalLayout ) return 0; #if VCL_FLOAT_DEVICE_PIXEL @@ -1191,7 +1194,8 @@ void OutputDevice::DrawStretchText( const Point& rStartPt, sal_uLong nWidth, ImplLayoutArgs OutputDevice::ImplPrepareLayoutArgs( OUString& rStr, const sal_Int32 nMinIndex, const sal_Int32 nLen, DeviceCoordinate nPixelWidth, const DeviceCoordinate* pDXArray, - int nLayoutFlags ) const + int nLayoutFlags, + vcl::TextLayoutCache const*const pLayoutCache) const { assert(nMinIndex >= 0); assert(nLen >= 0); @@ -1290,7 +1294,7 @@ ImplLayoutArgs OutputDevice::ImplPrepareLayoutArgs( OUString& rStr, nLayoutFlags |= SAL_LAYOUT_RIGHT_ALIGN; // set layout options - ImplLayoutArgs aLayoutArgs( rStr.getStr(), rStr.getLength(), nMinIndex, nEndIndex, nLayoutFlags, maFont.GetLanguageTag() ); + ImplLayoutArgs aLayoutArgs( rStr.getStr(), rStr.getLength(), nMinIndex, nEndIndex, nLayoutFlags, maFont.GetLanguageTag(), pLayoutCache ); int nOrientation = mpFontEntry ? mpFontEntry->mnOrientation : 0; aLayoutArgs.SetOrientation( nOrientation ); @@ -1304,7 +1308,8 @@ ImplLayoutArgs OutputDevice::ImplPrepareLayoutArgs( OUString& rStr, SalLayout* OutputDevice::ImplLayout(const OUString& rOrigStr, sal_Int32 nMinIndex, sal_Int32 nLen, const Point& rLogicalPos, long nLogicalWidth, - const long* pDXArray, int flags) const + const long* pDXArray, int flags, + vcl::TextLayoutCache const* pLayoutCache) const { // we need a graphics if( !mpGraphics ) @@ -1333,6 +1338,7 @@ SalLayout* OutputDevice::ImplLayout(const OUString& rOrigStr, // recode string if needed if( mpFontEntry->mpConversion ) { mpFontEntry->mpConversion->RecodeString( aStr, 0, aStr.getLength() ); + pLayoutCache = nullptr; // don't use cache with modified string! } DeviceCoordinate nPixelWidth = (DeviceCoordinate)nLogicalWidth; DeviceCoordinate* pDXPixelArray = NULL; @@ -1368,7 +1374,8 @@ SalLayout* OutputDevice::ImplLayout(const OUString& rOrigStr, } } - ImplLayoutArgs aLayoutArgs = ImplPrepareLayoutArgs( aStr, nMinIndex, nLen, nPixelWidth, pDXPixelArray, flags); + ImplLayoutArgs aLayoutArgs = ImplPrepareLayoutArgs( aStr, nMinIndex, nLen, + nPixelWidth, pDXPixelArray, flags, pLayoutCache); // get matching layout object for base font SalLayout* pSalLayout = mpGraphics->GetTextLayout( aLayoutArgs, 0 ); @@ -1407,6 +1414,24 @@ SalLayout* OutputDevice::ImplLayout(const OUString& rOrigStr, return pSalLayout; } +std::shared_ptr<vcl::TextLayoutCache> OutputDevice::CreateTextLayoutCache( + OUString const& rString) const +{ + if (!mpGraphics) // can happen in e.g Insert Index/Table dialog + return nullptr; + OUString copyBecausePrepareModifiesIt(rString); + ImplLayoutArgs aLayoutArgs = ImplPrepareLayoutArgs(copyBecausePrepareModifiesIt, + 0, rString.getLength(), 0, nullptr, 0, nullptr); + + SalLayout *const pSalLayout = mpGraphics->GetTextLayout( aLayoutArgs, 0 ); + if (!pSalLayout) + return nullptr; + std::shared_ptr<vcl::TextLayoutCache> const ret( + pSalLayout->CreateTextLayoutCache(copyBecausePrepareModifiesIt)); + pSalLayout->Release(); + return ret; +} + bool OutputDevice::GetTextIsRTL( const OUString& rString, sal_Int32 nIndex, sal_Int32 nLen ) const { OUString aStr( rString ); @@ -1420,9 +1445,11 @@ bool OutputDevice::GetTextIsRTL( const OUString& rString, sal_Int32 nIndex, sal_ sal_Int32 OutputDevice::GetTextBreak( const OUString& rStr, long nTextWidth, sal_Int32 nIndex, sal_Int32 nLen, - long nCharExtra ) const + long nCharExtra, + vcl::TextLayoutCache const*const pLayoutCache) const { - SalLayout* pSalLayout = ImplLayout( rStr, nIndex, nLen ); + SalLayout *const pSalLayout = ImplLayout( rStr, nIndex, nLen, + Point(0,0), 0, nullptr, 0, pLayoutCache); sal_Int32 nRetVal = -1; if( pSalLayout ) { @@ -1451,11 +1478,13 @@ sal_Int32 OutputDevice::GetTextBreak( const OUString& rStr, long nTextWidth, sal_Int32 OutputDevice::GetTextBreak( const OUString& rStr, long nTextWidth, sal_Unicode nHyphenChar, sal_Int32& rHyphenPos, sal_Int32 nIndex, sal_Int32 nLen, - long nCharExtra ) const + long nCharExtra, + vcl::TextLayoutCache const*const pLayoutCache) const { rHyphenPos = -1; - SalLayout* pSalLayout = ImplLayout( rStr, nIndex, nLen ); + SalLayout *const pSalLayout = ImplLayout( rStr, nIndex, nLen, + Point(0,0), 0, nullptr, 0, pLayoutCache); sal_Int32 nRetVal = -1; if( pSalLayout ) { |