editeng/inc/outleeng.hxx | 16 editeng/source/editeng/editeng.cxx | 23 editeng/source/editeng/impedit.hxx | 5 editeng/source/editeng/impedit3.cxx | 42 - editeng/source/outliner/outleeng.cxx | 22 editeng/source/outliner/outliner.cxx | 74 -- include/editeng/editeng.hxx | 25 include/editeng/outliner.hxx | 80 -- include/svx/svdotext.hxx | 14 sd/source/ui/view/outlview.cxx | 1 svx/source/svdraw/svdotextdecomposition.cxx | 832 ++++++++++++------------ svx/source/svdraw/svdotextpathdecomposition.cxx | 13 12 files changed, 550 insertions(+), 597 deletions(-)
New commits: commit 3da11981797a45f83195d63c20818f315406e3dd Author: Armin Le Grand (Collabora) <[email protected]> AuthorDate: Thu Mar 27 12:01:13 2025 +0100 Commit: Armin Le Grand <[email protected]> CommitDate: Thu Mar 27 18:56:22 2025 +0100 Make conversion to Primitives more accessible for EditEngine/Outliner When checking how TextEdit on the Overlay may be doable in Calc I stumbled about that I initially did that based on Outliner (svx) for all DrawObjects/Draw/Impress, but it is not accessible from EditEngine. Calc again just uses an EditEngine for TextEdit in Cell, so I checked doability. Quite some stuff has to be changed, basically instead of unsing IMPL/DECL_LINK I use lambda functions now. The former callbacks were anyways exclusively used for this and had no general used case. Also simplified and cleaned up quite some other stuff, some member functions could be removed, some helper classes deleted or simplified/streamlined. This should do no change to existing decomposes or edit views, but will make it possible to move in the direction of CellEdit on the Overlay and also prepares decompositions there to allow going in the direction of primitive based paints in Calc. Change-Id: Ia9c4c1129c9579ba4870b091977082e5f0d319f8 Reviewed-on: https://gerrit.libreoffice.org/c/core/+/183388 Reviewed-by: Armin Le Grand <[email protected]> Tested-by: Jenkins diff --git a/editeng/inc/outleeng.hxx b/editeng/inc/outleeng.hxx index 892c336d3290..5415c26810fb 100644 --- a/editeng/inc/outleeng.hxx +++ b/editeng/inc/outleeng.hxx @@ -35,24 +35,14 @@ public: OutlinerEditEng( Outliner* pOwner, SfxItemPool* pPool ); virtual ~OutlinerEditEng() override; - virtual void PaintingFirstLine(sal_Int32 nPara, const Point& rStartPos, const Point& rOrigin, Degree10 nOrientation, OutputDevice& rOutDev) override; + virtual void PaintingFirstLine(sal_Int32 nPara, const Point& rStartPos, const Point& rOrigin, Degree10 nOrientation, OutputDevice& rOutDev, + const std::function<void(const DrawPortionInfo&)>& rDrawPortion, + const std::function<void(const DrawBulletInfo&)>& rDrawBullet) override; virtual void ParagraphInserted( sal_Int32 nNewParagraph ) override; virtual void ParagraphDeleted( sal_Int32 nDeletedParagraph ) override; virtual void ParagraphConnected( sal_Int32 nLeftParagraph, sal_Int32 nRightParagraph ) override; - virtual void DrawingText( const Point& rStartPos, const OUString& rText, sal_Int32 nTextStart, - sal_Int32 nTextLen, KernArraySpan pDXArray, - std::span<const sal_Bool> pKashidaArray, const SvxFont& rFont, - sal_Int32 nPara, sal_uInt8 nRightToLeft, - const EEngineData::WrongSpellVector* pWrongSpellVector, - const SvxFieldData* pFieldData, - bool bEndOfLine, - bool bEndOfParagraph, - const css::lang::Locale* pLocale, - const Color& rOverlineColor, - const Color& rTextLineColor) override; - virtual void StyleSheetChanged( SfxStyleSheet* pStyle ) override; virtual void ParaAttribsChanged( sal_Int32 nPara ) override; virtual bool SpellNextDocument() override; diff --git a/editeng/source/editeng/editeng.cxx b/editeng/source/editeng/editeng.cxx index ee4f23275377..8a8a3029d6e1 100644 --- a/editeng/source/editeng/editeng.cxx +++ b/editeng/source/editeng/editeng.cxx @@ -1071,8 +1071,13 @@ SvxFont EditEngine::GetStandardSvxFont( sal_Int32 nPara ) return pNode->GetCharAttribs().GetDefFont(); } -void EditEngine::StripPortions() +void EditEngine::StripPortions( + const std::function<void(const DrawPortionInfo&)>& rDrawPortion, + const std::function<void(const DrawBulletInfo&)>& rDrawBullet) { + if (!rDrawPortion && !rDrawBullet) + return; + ScopedVclPtrInstance< VirtualDevice > aTmpDev; tools::Rectangle aBigRect( Point( 0, 0 ), Size( 0x7FFFFFFF, 0x7FFFFFFF ) ); if ( IsEffectivelyVertical() ) @@ -1088,7 +1093,8 @@ void EditEngine::StripPortions() aBigRect.SetBottom( 0 ); } } - getImpl().Paint(*aTmpDev, aBigRect, Point(), true); + + getImpl().Paint(*aTmpDev, aBigRect, Point(), 0_deg10, rDrawPortion, rDrawBullet); } void EditEngine::GetPortions( sal_Int32 nPara, std::vector<sal_Int32>& rList ) @@ -1578,16 +1584,9 @@ EditEngine::CreateTransferable(const ESelection& rSelection) // ====================== Virtual Methods ======================== -void EditEngine::DrawingText( const Point&, const OUString&, sal_Int32, sal_Int32, - KernArraySpan, std::span<const sal_Bool>, - const SvxFont&, sal_Int32 /*nPara*/, sal_uInt8 /*nRightToLeft*/, - const EEngineData::WrongSpellVector*, const SvxFieldData*, bool, bool, - const css::lang::Locale*, const Color&, const Color&) - -{ -} - -void EditEngine::PaintingFirstLine(sal_Int32, const Point&, const Point&, Degree10, OutputDevice&) +void EditEngine::PaintingFirstLine(sal_Int32, const Point&, const Point&, Degree10, OutputDevice&, + const std::function<void(const DrawPortionInfo&)>&, + const std::function<void(const DrawBulletInfo&)>&) { } diff --git a/editeng/source/editeng/impedit.hxx b/editeng/source/editeng/impedit.hxx index 24d30ba3b559..f99e6d7cc469 100644 --- a/editeng/source/editeng/impedit.hxx +++ b/editeng/source/editeng/impedit.hxx @@ -992,7 +992,10 @@ public: void Draw( OutputDevice& rOutDev, const tools::Rectangle& rOutRect, const Point& rStartDocPos, bool bClip ); void UpdateViews( EditView* pCurView = nullptr ); void Paint( ImpEditView* pView, const tools::Rectangle& rRect, OutputDevice* pTargetDevice ); - void Paint(OutputDevice& rOutDev, tools::Rectangle aClipRect, Point aStartPos, bool bStripOnly = false, Degree10 nOrientation = 0_deg10); + void Paint( + OutputDevice& rOutDev, tools::Rectangle aClipRect, Point aStartPos, Degree10 nOrientation = 0_deg10, + const std::function<void(const DrawPortionInfo&)>& rDrawPortion = std::function<void(const DrawPortionInfo&)>(), + const std::function<void(const DrawBulletInfo&)>& rDrawBullet = std::function<void(const DrawBulletInfo&)>()); bool MouseButtonUp( const MouseEvent& rMouseEvent, EditView* pView ); bool MouseButtonDown( const MouseEvent& rMouseEvent, EditView* pView ); diff --git a/editeng/source/editeng/impedit3.cxx b/editeng/source/editeng/impedit3.cxx index 6b86cbd0962b..fd214f2cc1c7 100644 --- a/editeng/source/editeng/impedit3.cxx +++ b/editeng/source/editeng/impedit3.cxx @@ -3242,7 +3242,7 @@ void ImpEditEngine::Draw( OutputDevice& rOutDev, const Point& rStartPos, Degree1 aStartPos.AdjustX(GetPaperSize().Width() ); rStartPos.RotateAround(aStartPos, nOrientation); } - Paint(rOutDev, aBigRect, aStartPos, false, nOrientation); + Paint(rOutDev, aBigRect, aStartPos, nOrientation); if (rOutDev.GetConnectMetaFile()) rOutDev.Pop(); } @@ -3316,9 +3316,11 @@ void ImpEditEngine::Draw( OutputDevice& rOutDev, const tools::Rectangle& rOutRec } // TODO: use IterateLineAreas in ImpEditEngine::Paint, to avoid algorithm duplication -void ImpEditEngine::Paint( OutputDevice& rOutDev, tools::Rectangle aClipRect, Point aStartPos, bool bStripOnly, Degree10 nOrientation ) +void ImpEditEngine::Paint( OutputDevice& rOutDev, tools::Rectangle aClipRect, Point aStartPos, Degree10 nOrientation, + const std::function<void(const DrawPortionInfo&)>& rDrawPortion, + const std::function<void(const DrawBulletInfo&)>& rDrawBullet) { - if ( !IsUpdateLayout() && !bStripOnly ) + if ( !IsUpdateLayout() && !rDrawPortion ) return; if ( !IsFormatted() ) @@ -3408,7 +3410,8 @@ void ImpEditEngine::Paint( OutputDevice& rOutDev, tools::Rectangle aClipRect, Po { Point aLineStart(aStartPos); adjustYDirectionAware(aLineStart, -nLineHeight); - GetEditEnginePtr()->PaintingFirstLine(nParaPortion, aLineStart, aOrigin, nOrientation, rOutDev); + GetEditEnginePtr()->PaintingFirstLine(nParaPortion, aLineStart, aOrigin, nOrientation, rOutDev, + rDrawPortion, rDrawBullet); // Remember whether a bullet was painted. const SfxBoolItem& rBulletState = mpEditEngine->GetParaAttrib(nParaPortion, EE_PARA_BULLETSTATE); @@ -3595,7 +3598,7 @@ void ImpEditEngine::Paint( OutputDevice& rOutDev, tools::Rectangle aClipRect, Po //It is not perfect, it still use lineBreaksList, so it won’t seek //word ends to wrap text there, but it would be difficult to change //this due to needed adaptations in EditEngine - if (bStripOnly && !bParsingFields && pExtraInfo && !pExtraInfo->lineBreaksList.empty()) + if (rDrawPortion && !bParsingFields && pExtraInfo && !pExtraInfo->lineBreaksList.empty()) { bParsingFields = true; itSubLines = pExtraInfo->lineBreaksList.begin(); @@ -3699,7 +3702,7 @@ void ImpEditEngine::Paint( OutputDevice& rOutDev, tools::Rectangle aClipRect, Po if (rTextPortion.IsRightToLeft()) aRedLineTmpPos.AdjustX(rTextPortion.GetSize().Width() ); - if ( bStripOnly ) + if ( rDrawPortion ) { EEngineData::WrongSpellVector aWrongSpellVector; @@ -3783,14 +3786,16 @@ void ImpEditEngine::Paint( OutputDevice& rOutDev, tools::Rectangle aClipRect, Po ImplCalcDigitLang(aTmpFont.GetLanguage())); // StripPortions() data callback - GetEditEnginePtr()->DrawingText( aOutPos, aText, nTextStart, nTextLen, pDXArray, pKashidaArray, + const DrawPortionInfo aInfo( + aOutPos, aText, nTextStart, nTextLen, pDXArray, pKashidaArray, aTmpFont, nParaPortion, rTextPortion.GetRightToLeftLevel(), !aWrongSpellVector.empty() ? &aWrongSpellVector : nullptr, pFieldData, - bEndOfLine, bEndOfParagraph, // support for EOL/EOP TEXT comments + bEndOfLine, bEndOfParagraph, false, // support for EOL/EOP TEXT comments &aLocale, aOverlineColor, aTextLineColor); + rDrawPortion(aInfo); // #108052# remember that EOP is written already for this ParaPortion if(bEndOfParagraph) @@ -4015,7 +4020,7 @@ void ImpEditEngine::Paint( OutputDevice& rOutDev, tools::Rectangle aClipRect, Po comphelper::string::padToLength(aBuf, nChars, rTextPortion.GetExtraValue()); OUString aText(aBuf.makeStringAndClear()); - if ( bStripOnly ) + if ( rDrawPortion ) { // create EOL and EOP bools const bool bEndOfLine(nPortion == pLine->GetEndPortion()); @@ -4025,15 +4030,16 @@ void ImpEditEngine::Paint( OutputDevice& rOutDev, tools::Rectangle aClipRect, Po const Color aTextLineColor(rOutDev.GetTextLineColor()); // StripPortions() data callback - GetEditEnginePtr()->DrawingText( + const DrawPortionInfo aInfo( aTmpPos, aText, 0, aText.getLength(), {}, {}, aTmpFont, nParaPortion, 0, nullptr, nullptr, - bEndOfLine, bEndOfParagraph, + bEndOfLine, bEndOfParagraph, false, nullptr, aOverlineColor, aTextLineColor); + rDrawPortion(aInfo); } else { @@ -4042,7 +4048,7 @@ void ImpEditEngine::Paint( OutputDevice& rOutDev, tools::Rectangle aClipRect, Po rOutDev.DrawStretchText( aTmpPos, rTextPortion.GetSize().Width(), aText ); } } - else if ( bStripOnly ) + else if ( rDrawPortion ) { // #i108052# When stripping, a callback for _empty_ paragraphs is also needed. // This was optimized away (by not rendering the space-only tab portion), so do @@ -4053,15 +4059,16 @@ void ImpEditEngine::Paint( OutputDevice& rOutDev, tools::Rectangle aClipRect, Po const Color aOverlineColor(rOutDev.GetOverlineColor()); const Color aTextLineColor(rOutDev.GetTextLineColor()); - GetEditEnginePtr()->DrawingText( + const DrawPortionInfo aInfo( aTmpPos, OUString(), 0, 0, {}, {}, aTmpFont, nParaPortion, 0, nullptr, nullptr, - bEndOfLine, bEndOfParagraph, + bEndOfLine, bEndOfParagraph, false, nullptr, aOverlineColor, aTextLineColor); + rDrawPortion(aInfo); } } break; @@ -4097,20 +4104,21 @@ void ImpEditEngine::Paint( OutputDevice& rOutDev, tools::Rectangle aClipRect, Po // that the reason for #i108052# was fixed/removed again, so this is a try to fix // the number of paragraphs (and counting empty ones) now independent from the // changes in EditEngine behaviour. - if(!bEndOfParagraphWritten && !bPaintBullet && bStripOnly) + if(!bEndOfParagraphWritten && !bPaintBullet && rDrawPortion) { const Color aOverlineColor(rOutDev.GetOverlineColor()); const Color aTextLineColor(rOutDev.GetTextLineColor()); - GetEditEnginePtr()->DrawingText( + const DrawPortionInfo aInfo( aTmpPos, OUString(), 0, 0, {}, {}, aTmpFont, nParaPortion, 0, nullptr, nullptr, - false, true, // support for EOL/EOP TEXT comments + false, true, false, // support for EOL/EOP TEXT comments nullptr, aOverlineColor, aTextLineColor); + rDrawPortion(aInfo); } } else diff --git a/editeng/source/outliner/outleeng.cxx b/editeng/source/outliner/outleeng.cxx index da297400382b..68e3dcca07ae 100644 --- a/editeng/source/outliner/outleeng.cxx +++ b/editeng/source/outliner/outleeng.cxx @@ -39,7 +39,10 @@ OutlinerEditEng::~OutlinerEditEng() { } -void OutlinerEditEng::PaintingFirstLine(sal_Int32 nPara, const Point& rStartPos, const Point& rOrigin, Degree10 nOrientation, OutputDevice& rOutDev) +void OutlinerEditEng::PaintingFirstLine(sal_Int32 nPara, const Point& rStartPos, const Point& rOrigin, Degree10 nOrientation, OutputDevice& rOutDev, + const std::function<void(const DrawPortionInfo&)>& rDrawPortion, + const std::function<void(const DrawBulletInfo&)>& rDrawBullet +) { if( GetControlWord() & EEControlBits::OUTLINER ) { @@ -47,7 +50,7 @@ void OutlinerEditEng::PaintingFirstLine(sal_Int32 nPara, const Point& rStartPos, pOwner->maPaintFirstLineHdl.Call( &aInfo ); } - pOwner->PaintBullet(nPara, rStartPos, rOrigin, nOrientation, rOutDev); + pOwner->PaintBullet(nPara, rStartPos, rOrigin, nOrientation, rOutDev, rDrawPortion, rDrawBullet); } const SvxNumberFormat* OutlinerEditEng::GetNumberFormat( sal_Int32 nPara ) const @@ -150,21 +153,6 @@ OUString OutlinerEditEng::GetUndoComment( sal_uInt16 nUndoId ) const } } -void OutlinerEditEng::DrawingText( const Point& rStartPos, const OUString& rText, sal_Int32 nTextStart, sal_Int32 nTextLen, - KernArraySpan pDXArray, std::span<const sal_Bool> pKashidaArray, - const SvxFont& rFont, sal_Int32 nPara, sal_uInt8 nRightToLeft, - const EEngineData::WrongSpellVector* pWrongSpellVector, - const SvxFieldData* pFieldData, - bool bEndOfLine, - bool bEndOfParagraph, - const css::lang::Locale* pLocale, - const Color& rOverlineColor, - const Color& rTextLineColor) -{ - pOwner->DrawingText(rStartPos,rText,nTextStart,nTextLen,pDXArray,pKashidaArray,rFont,nPara,nRightToLeft, - pWrongSpellVector, pFieldData, bEndOfLine, bEndOfParagraph, false/*bEndOfBullet*/, pLocale, rOverlineColor, rTextLineColor); -} - OUString OutlinerEditEng::CalcFieldValue( const SvxFieldItem& rField, sal_Int32 nPara, sal_Int32 nPos, std::optional<Color>& rpTxtColor, std::optional<Color>& rpFldColor, std::optional<FontLineStyle>& rpFldLineStyle ) { return pOwner->CalcFieldValue( rField, nPara, nPos, rpTxtColor, rpFldColor, rpFldLineStyle ); diff --git a/editeng/source/outliner/outliner.cxx b/editeng/source/outliner/outliner.cxx index b1e65c95219f..b4c566b0ee10 100644 --- a/editeng/source/outliner/outliner.cxx +++ b/editeng/source/outliner/outliner.cxx @@ -869,8 +869,11 @@ vcl::Font Outliner::ImpCalcBulletFont( sal_Int32 nPara ) const return aBulletFont; } -void Outliner::PaintBullet(sal_Int32 nPara, const Point& rStartPos, const Point& rOrigin, - Degree10 nOrientation, OutputDevice& rOutDev) +void Outliner::PaintBullet( + sal_Int32 nPara, const Point& rStartPos, const Point& rOrigin, + Degree10 nOrientation, OutputDevice& rOutDev, + const std::function<void(const DrawPortionInfo&)>& rDrawPortion, + const std::function<void(const DrawBulletInfo&)>& rDrawBullet) { bool bDrawBullet = false; @@ -954,9 +957,9 @@ void Outliner::PaintBullet(sal_Int32 nPara, const Point& rStartPos, const Point& nLayoutMode |= vcl::text::ComplexTextLayoutFlags::BiDiRtl | vcl::text::ComplexTextLayoutFlags::TextOriginLeft | vcl::text::ComplexTextLayoutFlags::BiDiStrong; rOutDev.SetLayoutMode( nLayoutMode ); - if(bStrippingPortions) + if(rDrawPortion) { - const vcl::Font& aSvxFont(rOutDev.GetFont()); + const SvxFont aSvxFont(rOutDev.GetFont()); KernArray aBuf; rOutDev.GetTextArray( pPara->GetText(), &aBuf ); @@ -967,8 +970,10 @@ void Outliner::PaintBullet(sal_Int32 nPara, const Point& rStartPos, const Point& aTextPos.AdjustY( -(aMetric.GetDescent()) ); } - DrawingText(aTextPos, pPara->GetText(), 0, pPara->GetText().getLength(), aBuf, {}, + const DrawPortionInfo aInfo( + aTextPos, pPara->GetText(), 0, pPara->GetText().getLength(), aBuf, {}, aSvxFont, nPara, bRightToLeftPara ? 1 : 0, nullptr, nullptr, false, false, true, nullptr, Color(), Color()); + rDrawPortion(aInfo); } else { @@ -1004,21 +1009,17 @@ void Outliner::PaintBullet(sal_Int32 nPara, const Point& rStartPos, const Point& } } - if(bStrippingPortions) + if(rDrawBullet) { - if(aDrawBulletHdl.IsSet()) - { - // call something analog to aDrawPortionHdl (if set) and feed it something - // analog to DrawPortionInfo... - // created aDrawBulletHdl, Set/GetDrawBulletHdl. - // created DrawBulletInfo and added handling to sdrtextdecomposition.cxx - DrawBulletInfo aDrawBulletInfo( - *pFmt->GetBrush()->GetGraphicObject(), - aBulletPos, - pPara->aBulSize); - - aDrawBulletHdl.Call(&aDrawBulletInfo); - } + // call something analog to aDrawPortionHdl (if set) and feed it something + // analog to DrawPortionInfo... + // created aDrawBulletHdl, Set/GetDrawBulletHdl. + // created DrawBulletInfo and added handling to sdrtextdecomposition.cxx + DrawBulletInfo aDrawBulletInfo( + *pFmt->GetBrush()->GetGraphicObject(), + aBulletPos, + pPara->aBulSize); + rDrawBullet(aDrawBulletInfo); } else { @@ -1029,8 +1030,7 @@ void Outliner::PaintBullet(sal_Int32 nPara, const Point& rStartPos, const Point& } // In case of collapsed subparagraphs paint a line before the text. - if( !pParaList->HasChildren(pPara) || pParaList->HasVisibleChildren(pPara) || - bStrippingPortions || nOrientation ) + if( !pParaList->HasChildren(pPara) || pParaList->HasVisibleChildren(pPara) || rDrawPortion || nOrientation ) return; tools::Long nWidth = rOutDev.PixelToLogic( Size( 10, 0 ) ).Width(); @@ -1231,7 +1231,6 @@ Outliner::Outliner(SfxItemPool* pPool, OutlinerMode nMode) , nMaxDepth(9) , bFirstParaIsEmpty(true) , nBlockInsCallback(0) - , bStrippingPortions(false) , bPasting(false) { @@ -1637,34 +1636,11 @@ void Outliner::Remove( Paragraph const * pPara, sal_Int32 nParaCount ) } } -void Outliner::StripPortions() -{ - bStrippingPortions = true; - pEditEngine->StripPortions(); - bStrippingPortions = false; -} - -void Outliner::DrawingText( const Point& rStartPos, const OUString& rText, sal_Int32 nTextStart, - sal_Int32 nTextLen, std::span<const double> pDXArray, - std::span<const sal_Bool> pKashidaArray, const SvxFont& rFont, - sal_Int32 nPara, sal_uInt8 nRightToLeft, - const EEngineData::WrongSpellVector* pWrongSpellVector, - const SvxFieldData* pFieldData, - bool bEndOfLine, - bool bEndOfParagraph, - bool bEndOfBullet, - const css::lang::Locale* pLocale, - const Color& rOverlineColor, - const Color& rTextLineColor) +void Outliner::StripPortions( + const std::function<void(const DrawPortionInfo&)>& rDrawPortion, + const std::function<void(const DrawBulletInfo&)>& rDrawBullet) { - if(aDrawPortionHdl.IsSet()) - { - DrawPortionInfo aInfo( rStartPos, rText, nTextStart, nTextLen, rFont, nPara, pDXArray, pKashidaArray, pWrongSpellVector, - pFieldData, pLocale, rOverlineColor, rTextLineColor, nRightToLeft, - bEndOfLine, bEndOfParagraph, bEndOfBullet); - - aDrawPortionHdl.Call( &aInfo ); - } + pEditEngine->StripPortions(rDrawPortion, rDrawBullet); } bool Outliner::RemovingPagesHdl( OutlinerView* pView ) diff --git a/include/editeng/editeng.hxx b/include/editeng/editeng.hxx index 8695b3ae0f14..3b0277f9335d 100644 --- a/include/editeng/editeng.hxx +++ b/include/editeng/editeng.hxx @@ -114,6 +114,8 @@ class ParaPortionList; enum class CharCompressType; enum class TransliterationFlags; class LinkParamNone; +class DrawPortionInfo; +class DrawBulletInfo; /** values for: SfxItemSet GetAttribs( const ESelection& rSel, EditEngineAttribs nOnlyHardAttrib = EditEngineAttribs::All ); @@ -367,7 +369,9 @@ public: bool IsInSelectionMode() const; - SAL_DLLPRIVATE void StripPortions(); + void StripPortions( + const std::function<void(const DrawPortionInfo&)>& rDrawPortion, + const std::function<void(const DrawBulletInfo&)>& rDrawBullet); void GetPortions( sal_Int32 nPara, std::vector<sal_Int32>& rList ); SAL_DLLPRIVATE tools::Long GetFirstLineStartX( sal_Int32 nParagraph ); @@ -488,7 +492,10 @@ public: SAL_DLLPRIVATE void SetBeginPasteOrDropHdl( const Link<PasteOrDropInfos&,void>& rLink ); SAL_DLLPRIVATE void SetEndPasteOrDropHdl( const Link<PasteOrDropInfos&,void>& rLink ); - virtual void PaintingFirstLine(sal_Int32 nPara, const Point& rStartPos, const Point& rOrigin, Degree10 nOrientation, OutputDevice& rOutDev); + virtual void PaintingFirstLine(sal_Int32 nPara, const Point& rStartPos, const Point& rOrigin, Degree10 nOrientation, OutputDevice& rOutDev, + const std::function<void(const DrawPortionInfo&)>& rDrawPortion, + const std::function<void(const DrawBulletInfo&)>& rDrawBullet); + virtual void ParagraphInserted( sal_Int32 nNewParagraph ); virtual void ParagraphDeleted( sal_Int32 nDeletedParagraph ); virtual void ParagraphConnected( sal_Int32 nLeftParagraph, sal_Int32 nRightParagraph ); @@ -496,20 +503,6 @@ public: virtual void StyleSheetChanged( SfxStyleSheet* pStyle ); SAL_DLLPRIVATE void ParagraphHeightChanged( sal_Int32 nPara ); - virtual void DrawingText( const Point& rStartPos, const OUString& rText, - sal_Int32 nTextStart, sal_Int32 nTextLen, - KernArraySpan pDXArray, - std::span<const sal_Bool> pKashidaArray, - const SvxFont& rFont, - sal_Int32 nPara, sal_uInt8 nRightToLeft, - const EEngineData::WrongSpellVector* pWrongSpellVector, - const SvxFieldData* pFieldData, - bool bEndOfLine, - bool bEndOfParagraph, - const css::lang::Locale* pLocale, - const Color& rOverlineColor, - const Color& rTextLineColor); - virtual OUString GetUndoComment( sal_uInt16 nUndoId ) const; virtual bool SpellNextDocument(); /** @return true, when click was consumed. false otherwise. */ diff --git a/include/editeng/outliner.hxx b/include/editeng/outliner.hxx index c6363520e1bc..d1c6c840ca07 100644 --- a/include/editeng/outliner.hxx +++ b/include/editeng/outliner.hxx @@ -406,22 +406,19 @@ public: const OUString maText; sal_Int32 mnTextStart; sal_Int32 mnTextLen; - sal_Int32 mnPara; - const SvxFont& mrFont; - KernArraySpan mpDXArray; + KernArraySpan mpDXArray; std::span<const sal_Bool> mpKashidaArray; - + const SvxFont& mrFont; + sal_Int32 mnPara; + sal_uInt8 mnBiDiLevel; const EEngineData::WrongSpellVector* mpWrongSpellVector; const SvxFieldData* mpFieldData; - const css::lang::Locale* mpLocale; - const Color maOverlineColor; - const Color maTextLineColor; - - sal_uInt8 mnBiDiLevel; - bool mbEndOfLine : 1; bool mbEndOfParagraph : 1; bool mbEndOfBullet : 1; + const css::lang::Locale* mpLocale; + const Color maOverlineColor; + const Color maTextLineColor; bool IsRTL() const { return mnBiDiLevel % 2 == 1; } @@ -430,36 +427,36 @@ public: OUString aTxt, sal_Int32 nTxtStart, sal_Int32 nTxtLen, - const SvxFont& rFnt, - sal_Int32 nPar, KernArraySpan pDXArr, std::span<const sal_Bool> pKashidaArr, + const SvxFont& rFnt, + sal_Int32 nPar, + sal_uInt8 nBiDiLevel, const EEngineData::WrongSpellVector* pWrongSpellVector, const SvxFieldData* pFieldData, - const css::lang::Locale* pLocale, - const Color& rOverlineColor, - const Color& rTextLineColor, - sal_uInt8 nBiDiLevel, bool bEndOfLine, bool bEndOfParagraph, - bool bEndOfBullet) + bool bEndOfBullet, + const css::lang::Locale* pLocale, + const Color& rOverlineColor, + const Color& rTextLineColor) : mrStartPos(rPos), maText(std::move(aTxt)), mnTextStart(nTxtStart), mnTextLen(nTxtLen), - mnPara(nPar), - mrFont(rFnt), mpDXArray(pDXArr), mpKashidaArray(pKashidaArr), + mrFont(rFnt), + mnPara(nPar), + mnBiDiLevel(nBiDiLevel), mpWrongSpellVector(pWrongSpellVector), mpFieldData(pFieldData), - mpLocale(pLocale), - maOverlineColor(rOverlineColor), - maTextLineColor(rTextLineColor), - mnBiDiLevel(nBiDiLevel), mbEndOfLine(bEndOfLine), mbEndOfParagraph(bEndOfParagraph), - mbEndOfBullet(bEndOfBullet) + mbEndOfBullet(bEndOfBullet), + mpLocale(pLocale), + maOverlineColor(rOverlineColor), + maTextLineColor(rTextLineColor) {} }; @@ -591,8 +588,6 @@ private: ViewList aViewList; sal_Int32 mnFirstSelPage; - Link<DrawPortionInfo*,void> aDrawPortionHdl; - Link<DrawBulletInfo*,void> aDrawBulletHdl; Link<ParagraphHdlParam,void> aParaInsertedHdl; Link<ParagraphHdlParam,void> aParaRemovingHdl; Link<DepthChangeHdlParam,void> aDepthChangedHdl; @@ -613,7 +608,6 @@ private: bool bFirstParaIsEmpty; sal_uInt8 nBlockInsCallback; - bool bStrippingPortions; bool bPasting; Link<EENotify&,void> aOutlinerNotifyHdl; @@ -657,9 +651,12 @@ protected: SAL_DLLPRIVATE void StyleSheetChanged( SfxStyleSheet const * pStyle ); SAL_DLLPRIVATE void InvalidateBullet(sal_Int32 nPara); - SAL_DLLPRIVATE void PaintBullet(sal_Int32 nPara, const Point& rStartPos, - const Point& rOrigin, Degree10 nOrientation, - OutputDevice& rOutDev); + SAL_DLLPRIVATE void PaintBullet( + sal_Int32 nPara, const Point& rStartPos, + const Point& rOrigin, Degree10 nOrientation, + OutputDevice& rOutDev, + const std::function<void(const DrawPortionInfo&)>& rDrawPortion, + const std::function<void(const DrawBulletInfo&)>& rDrawBullet); // used by OutlinerEditEng. Allows Outliner objects to provide // bullet access to the EditEngine. @@ -781,10 +778,6 @@ public: SAL_DLLPRIVATE void SetCalcFieldValueHdl(const Link<EditFieldInfo*,void>& rLink ) { aCalcFieldValueHdl= rLink; } SAL_DLLPRIVATE const Link<EditFieldInfo*,void>& GetCalcFieldValueHdl() const { return aCalcFieldValueHdl; } - SAL_DLLPRIVATE void SetDrawPortionHdl(const Link<DrawPortionInfo*,void>& rLink){aDrawPortionHdl=rLink;} - - SAL_DLLPRIVATE void SetDrawBulletHdl(const Link<DrawBulletInfo*,void>& rLink){aDrawBulletHdl=rLink;} - SAL_DLLPRIVATE void SetPaintFirstLineHdl(const Link<PaintFirstLineInfo*,void>& rLink) { maPaintFirstLineHdl = rLink; } void SetModifyHdl( const Link<LinkParamNone*,void>& rLink ); @@ -828,22 +821,9 @@ public: OUString const & GetWordDelimiters() const; OUString GetWord( const EPaM& rPos ); - void StripPortions(); - - SAL_DLLPRIVATE void DrawingText( const Point& rStartPos, const OUString& rText, - sal_Int32 nTextStart, sal_Int32 nTextLen, - KernArraySpan pDXArray, - std::span<const sal_Bool> pKashidaArray, - const SvxFont& rFont, - sal_Int32 nPara, sal_uInt8 nRightToLeft, - const EEngineData::WrongSpellVector* pWrongSpellVector, - const SvxFieldData* pFieldData, - bool bEndOfLine, - bool bEndOfParagraph, - bool bEndOfBullet, - const css::lang::Locale* pLocale, - const Color& rOverlineColor, - const Color& rTextLineColor); + void StripPortions( + const std::function<void(const DrawPortionInfo&)>& rDrawPortion, + const std::function<void(const DrawBulletInfo&)>& rDrawBullet); Size CalcTextSize(); diff --git a/include/svx/svdotext.hxx b/include/svx/svdotext.hxx index 899e81de4a0a..dea64305df03 100644 --- a/include/svx/svdotext.hxx +++ b/include/svx/svdotext.hxx @@ -116,8 +116,20 @@ namespace sdr::properties class CellProperties; } -// SdrTextObj +class DrawPortionInfo; +class DrawBulletInfo; +void SVXCORE_DLLPUBLIC CreateTextPortionPrimitivesFromDrawPortionInfo( + drawinglayer::primitive2d::Primitive2DContainer& rTarget, + const basegfx::B2DHomMatrix& rNewTransformA, + const basegfx::B2DHomMatrix& rNewTransformB, + const DrawPortionInfo& rInfo); +void SVXCORE_DLLPUBLIC CreateDrawBulletPrimitivesFromDrawBulletInfo( + drawinglayer::primitive2d::Primitive2DContainer& rTarget, + const basegfx::B2DHomMatrix& rNewTransformA, + const basegfx::B2DHomMatrix& rNewTransformB, + const DrawBulletInfo& rInfo); +// SdrTextObj class SVXCORE_DLLPUBLIC SdrTextObj : public SdrAttrObj, public svx::ITextProvider { private: diff --git a/sd/source/ui/view/outlview.cxx b/sd/source/ui/view/outlview.cxx index 3e713c912dae..f2f5ca1ffe1a 100644 --- a/sd/source/ui/view/outlview.cxx +++ b/sd/source/ui/view/outlview.cxx @@ -1300,7 +1300,6 @@ void OutlineView::ResetLinks() const mrOutliner.SetStatusEventHdl(Link<EditStatus&,void>()); mrOutliner.SetRemovingPagesHdl(Link<OutlinerView*,bool>()); mrOutliner.SetIndentingPagesHdl(Link<OutlinerView*,bool>()); - mrOutliner.SetDrawPortionHdl(Link<DrawPortionInfo*,void>()); mrOutliner.SetBeginPasteOrDropHdl(Link<PasteOrDropInfos*,void>()); mrOutliner.SetEndPasteOrDropHdl(Link<PasteOrDropInfos*,void>()); } diff --git a/svx/source/svdraw/svdotextdecomposition.cxx b/svx/source/svdraw/svdotextdecomposition.cxx index 8b235a21517a..b8dc0eb0448d 100644 --- a/svx/source/svdraw/svdotextdecomposition.cxx +++ b/svx/source/svdraw/svdotextdecomposition.cxx @@ -67,107 +67,76 @@ using namespace com::sun::star; // helpers - namespace { rtl::Reference<drawinglayer::primitive2d::BasePrimitive2D> buildTextPortionPrimitive(const DrawPortionInfo& rInfo, const OUString& rText, - const drawinglayer::attribute::FontAttribute& rFontAttribute, - const std::vector<double>& rDXArray, - const basegfx::B2DHomMatrix& rNewTransform); + const drawinglayer::attribute::FontAttribute& rFontAttribute, + const std::vector<double>& rDXArray, + const basegfx::B2DHomMatrix& rNewTransform); - class impTextBreakupHandler + // static rtl::Reference<drawinglayer::primitive2d::BasePrimitive2D> impCheckFieldPrimitive(drawinglayer::primitive2d::BasePrimitive2D* pPrimitive, const DrawPortionInfo& rInfo); + rtl::Reference<drawinglayer::primitive2d::BasePrimitive2D> CheckFieldPrimitive(drawinglayer::primitive2d::BasePrimitive2D* pPrimitive, const DrawPortionInfo& rInfo) { - private: - drawinglayer::primitive2d::Primitive2DContainer maTextPortionPrimitives; - drawinglayer::primitive2d::Primitive2DContainer maLinePrimitives; - drawinglayer::primitive2d::Primitive2DContainer maParagraphPrimitives; - - SdrOutliner& mrOutliner; - basegfx::B2DHomMatrix maNewTransformA; - basegfx::B2DHomMatrix maNewTransformB; - - // the visible area for contour text decomposition - basegfx::B2DVector maScale; - - // ClipRange for BlockText decomposition; only text portions completely - // inside are to be accepted, so this is different from geometric clipping - // (which would allow e.g. upper parts of portions to remain). Only used for - // BlockText (see there) - basegfx::B2DRange maClipRange; - - DECL_LINK(decomposeContourTextPrimitive, DrawPortionInfo*, void); - DECL_LINK(decomposeBlockTextPrimitive, DrawPortionInfo*, void); - DECL_LINK(decomposeStretchTextPrimitive, DrawPortionInfo*, void); - - DECL_LINK(decomposeContourBulletPrimitive, DrawBulletInfo*, void); - DECL_LINK(decomposeBlockBulletPrimitive, DrawBulletInfo*, void); - DECL_LINK(decomposeStretchBulletPrimitive, DrawBulletInfo*, void); - - static rtl::Reference<drawinglayer::primitive2d::BasePrimitive2D> impCheckFieldPrimitive(drawinglayer::primitive2d::BasePrimitive2D* pPrimitive, const DrawPortionInfo& rInfo); - void impFlushTextPortionPrimitivesToLinePrimitives(); - void impFlushLinePrimitivesToParagraphPrimitives(sal_Int32 nPara); - void impHandleDrawPortionInfo(const DrawPortionInfo& rInfo); - void impHandleDrawBulletInfo(const DrawBulletInfo& rInfo); - - public: - explicit impTextBreakupHandler(SdrOutliner& rOutliner) - : mrOutliner(rOutliner) + rtl::Reference<drawinglayer::primitive2d::BasePrimitive2D> xRet = pPrimitive; + if(rInfo.mpFieldData) { - } + // Support for FIELD_SEQ_BEGIN, FIELD_SEQ_END. If used, create a TextHierarchyFieldPrimitive2D + // which holds the field type and, if applicable, the URL + const SvxURLField* pURLField = dynamic_cast< const SvxURLField* >(rInfo.mpFieldData); + const SvxPageField* pPageField = dynamic_cast< const SvxPageField* >(rInfo.mpFieldData); - void decomposeContourTextPrimitive(const basegfx::B2DHomMatrix& rNewTransformA, const basegfx::B2DHomMatrix& rNewTransformB, const basegfx::B2DVector& rScale) - { - maScale = rScale; - maNewTransformA = rNewTransformA; - maNewTransformB = rNewTransformB; - mrOutliner.SetDrawPortionHdl(LINK(this, impTextBreakupHandler, decomposeContourTextPrimitive)); - mrOutliner.SetDrawBulletHdl(LINK(this, impTextBreakupHandler, decomposeContourBulletPrimitive)); - mrOutliner.StripPortions(); - mrOutliner.SetDrawPortionHdl(Link<DrawPortionInfo*,void>()); - mrOutliner.SetDrawBulletHdl(Link<DrawBulletInfo*,void>()); - } + // embed current primitive to a sequence + drawinglayer::primitive2d::Primitive2DContainer aSequence; - void decomposeBlockTextPrimitive( - const basegfx::B2DHomMatrix& rNewTransformA, - const basegfx::B2DHomMatrix& rNewTransformB, - const basegfx::B2DRange& rClipRange) - { - maNewTransformA = rNewTransformA; - maNewTransformB = rNewTransformB; - maClipRange = rClipRange; - mrOutliner.SetDrawPortionHdl(LINK(this, impTextBreakupHandler, decomposeBlockTextPrimitive)); - mrOutliner.SetDrawBulletHdl(LINK(this, impTextBreakupHandler, decomposeBlockBulletPrimitive)); - mrOutliner.StripPortions(); - mrOutliner.SetDrawPortionHdl(Link<DrawPortionInfo*,void>()); - mrOutliner.SetDrawBulletHdl(Link<DrawBulletInfo*,void>()); - } + if(pPrimitive) + { + aSequence.resize(1); + aSequence[0] = drawinglayer::primitive2d::Primitive2DReference(pPrimitive); + } - void decomposeStretchTextPrimitive(const basegfx::B2DHomMatrix& rNewTransformA, const basegfx::B2DHomMatrix& rNewTransformB) - { - maNewTransformA = rNewTransformA; - maNewTransformB = rNewTransformB; - mrOutliner.SetDrawPortionHdl(LINK(this, impTextBreakupHandler, decomposeStretchTextPrimitive)); - mrOutliner.SetDrawBulletHdl(LINK(this, impTextBreakupHandler, decomposeStretchBulletPrimitive)); - mrOutliner.StripPortions(); - mrOutliner.SetDrawPortionHdl(Link<DrawPortionInfo*,void>()); - mrOutliner.SetDrawBulletHdl(Link<DrawBulletInfo*,void>()); + if(pURLField) + { + // extended this to hold more of the contents of the original + // SvxURLField since that stuff is still used in HitTest and e.g. Calc + std::vector< std::pair< OUString, OUString>> meValues; + meValues.emplace_back("URL", pURLField->GetURL()); + meValues.emplace_back("Representation", pURLField->GetRepresentation()); + meValues.emplace_back("TargetFrame", pURLField->GetTargetFrame()); + meValues.emplace_back("AltText", pURLField->GetName()); + meValues.emplace_back("SvxURLFormat", OUString::number(static_cast<sal_uInt16>(pURLField->GetFormat()))); + xRet = new drawinglayer::primitive2d::TextHierarchyFieldPrimitive2D(std::move(aSequence), drawinglayer::primitive2d::FIELD_TYPE_URL, &meValues); + } + else if(pPageField) + { + xRet = new drawinglayer::primitive2d::TextHierarchyFieldPrimitive2D(std::move(aSequence), drawinglayer::primitive2d::FIELD_TYPE_PAGE); + } + else + { + xRet = new drawinglayer::primitive2d::TextHierarchyFieldPrimitive2D(std::move(aSequence), drawinglayer::primitive2d::FIELD_TYPE_COMMON); + } } - drawinglayer::primitive2d::Primitive2DContainer extractPrimitive2DSequence(); - - void impCreateTextPortionPrimitive(const DrawPortionInfo& rInfo); - }; + return xRet; + } class DoCapitalsDrawPortionInfo : public SvxDoCapitals { private: - impTextBreakupHandler& m_rHandler; + drawinglayer::primitive2d::Primitive2DContainer& mrTarget; + const basegfx::B2DHomMatrix& mrNewTransformA; + const basegfx::B2DHomMatrix& mrNewTransformB; const DrawPortionInfo& m_rInfo; SvxFont m_aFont; public: - DoCapitalsDrawPortionInfo(impTextBreakupHandler& rHandler, const DrawPortionInfo& rInfo) - : SvxDoCapitals(rInfo.maText, rInfo.mnTextStart, rInfo.mnTextLen) - , m_rHandler(rHandler) + DoCapitalsDrawPortionInfo( + drawinglayer::primitive2d::Primitive2DContainer& rTarget, + const basegfx::B2DHomMatrix& rNewTransformA, + const basegfx::B2DHomMatrix& rNewTransformB, + const DrawPortionInfo& rInfo) + : SvxDoCapitals(rInfo.maText, rInfo.mnTextStart, rInfo.mnTextLen) + , mrTarget(rTarget) + , mrNewTransformA(rNewTransformA) + , mrNewTransformB(rNewTransformB) , m_rInfo(rInfo) , m_aFont(rInfo.mrFont) { @@ -182,7 +151,7 @@ namespace m_aFont.SetCaseMap(SvxCaseMap::NotMapped); /* otherwise this would call itself */ } virtual void Do( const OUString &rSpanTxt, const sal_Int32 nSpanIdx, - const sal_Int32 nSpanLen, const bool bUpper ) override + const sal_Int32 nSpanLen, const bool bUpper ) override { sal_uInt8 nProp(0); if (!bUpper) @@ -206,258 +175,425 @@ namespace std::span<const sal_Bool>(); DrawPortionInfo aInfo(aStartPos, rSpanTxt, - nSpanIdx, nSpanLen, - m_aFont, m_rInfo.mnPara, - aDXArray, aKashidaArray, - nullptr, /* no spelling in subportion, handled outside */ - nullptr, /* no field in subportion, handled outside */ - m_rInfo.mpLocale, m_rInfo.maOverlineColor, m_rInfo.maTextLineColor, - m_rInfo.mnBiDiLevel, - false, false, false); - - m_rHandler.impCreateTextPortionPrimitive(aInfo); + nSpanIdx, nSpanLen, + aDXArray, aKashidaArray, + m_aFont, m_rInfo.mnPara, + m_rInfo.mnBiDiLevel, + nullptr, /* no spelling in subportion, handled outside */ + nullptr, /* no field in subportion, handled outside */ + false, false, false, + m_rInfo.mpLocale, m_rInfo.maOverlineColor, m_rInfo.maTextLineColor); + + CreateTextPortionPrimitivesFromDrawPortionInfo( + mrTarget, + mrNewTransformA, + mrNewTransformB, + aInfo); if (!bUpper) m_aFont.SetPropr(nProp); } }; +} // end of anonymous namespace - void impTextBreakupHandler::impCreateTextPortionPrimitive(const DrawPortionInfo& rInfo) - { - if(rInfo.maText.isEmpty() || !rInfo.mnTextLen) - return; - - basegfx::B2DVector aFontScaling; - drawinglayer::attribute::FontAttribute aFontAttribute( - drawinglayer::primitive2d::getFontAttributeFromVclFont( - aFontScaling, - rInfo.mrFont, - rInfo.IsRTL(), - false)); - basegfx::B2DHomMatrix aNewTransform; +void CreateTextPortionPrimitivesFromDrawPortionInfo( + drawinglayer::primitive2d::Primitive2DContainer& rTarget, + const basegfx::B2DHomMatrix& rNewTransformA, + const basegfx::B2DHomMatrix& rNewTransformB, + const DrawPortionInfo& rInfo) +{ + if(rInfo.maText.isEmpty() || !rInfo.mnTextLen) + return; - // add font scale to new transform - aNewTransform.scale(aFontScaling.getX(), aFontScaling.getY()); + basegfx::B2DVector aFontScaling; + drawinglayer::attribute::FontAttribute aFontAttribute( + drawinglayer::primitive2d::getFontAttributeFromVclFont( + aFontScaling, + rInfo.mrFont, + rInfo.IsRTL(), + false)); + basegfx::B2DHomMatrix aNewTransform; + + // add font scale to new transform + aNewTransform.scale(aFontScaling.getX(), aFontScaling.getY()); + + // look for proportional font scaling, if necessary, scale accordingly + sal_Int8 nPropr(rInfo.mrFont.GetPropr()); + const double fPropFontFactor(nPropr / 100.0); + if (100 != nPropr) + aNewTransform.scale(fPropFontFactor, fPropFontFactor); + + // apply font rotate + if(rInfo.mrFont.GetOrientation()) + { + aNewTransform.rotate(-toRadians(rInfo.mrFont.GetOrientation())); + } - // look for proportional font scaling, if necessary, scale accordingly - sal_Int8 nPropr(rInfo.mrFont.GetPropr()); - const double fPropFontFactor(nPropr / 100.0); - if (100 != nPropr) - aNewTransform.scale(fPropFontFactor, fPropFontFactor); + // look for escapement, if necessary, translate accordingly + if(rInfo.mrFont.GetEscapement()) + { + sal_Int16 nEsc(rInfo.mrFont.GetEscapement()); - // apply font rotate - if(rInfo.mrFont.GetOrientation()) + if(DFLT_ESC_AUTO_SUPER == nEsc) { - aNewTransform.rotate(-toRadians(rInfo.mrFont.GetOrientation())); + nEsc = .8 * (100 - nPropr); + assert (nEsc == DFLT_ESC_SUPER && "I'm sure this formula needs to be changed, but how to confirm that???"); + nEsc = DFLT_ESC_SUPER; } - - // look for escapement, if necessary, translate accordingly - if(rInfo.mrFont.GetEscapement()) + else if(DFLT_ESC_AUTO_SUB == nEsc) { - sal_Int16 nEsc(rInfo.mrFont.GetEscapement()); - - if(DFLT_ESC_AUTO_SUPER == nEsc) - { - nEsc = .8 * (100 - nPropr); - assert (nEsc == DFLT_ESC_SUPER && "I'm sure this formula needs to be changed, but how to confirm that???"); - nEsc = DFLT_ESC_SUPER; - } - else if(DFLT_ESC_AUTO_SUB == nEsc) - { - nEsc = .2 * -(100 - nPropr); - assert (nEsc == -20 && "I'm sure this formula needs to be changed, but how to confirm that???"); - nEsc = -20; - } - - if(nEsc > MAX_ESC_POS) - { - nEsc = MAX_ESC_POS; - } - else if(nEsc < -MAX_ESC_POS) - { - nEsc = -MAX_ESC_POS; - } + nEsc = .2 * -(100 - nPropr); + assert (nEsc == -20 && "I'm sure this formula needs to be changed, but how to confirm that???"); + nEsc = -20; + } - const double fEscapement(nEsc / -100.0); - aNewTransform.translate(0.0, fEscapement * aFontScaling.getY()); + if(nEsc > MAX_ESC_POS) + { + nEsc = MAX_ESC_POS; + } + else if(nEsc < -MAX_ESC_POS) + { + nEsc = -MAX_ESC_POS; } - // apply transformA - aNewTransform *= maNewTransformA; + const double fEscapement(nEsc / -100.0); + aNewTransform.translate(0.0, fEscapement * aFontScaling.getY()); + } - // apply local offset - aNewTransform.translate(rInfo.mrStartPos.X(), rInfo.mrStartPos.Y()); + // apply transformA + aNewTransform *= rNewTransformA; - // also apply embedding object's transform - aNewTransform *= maNewTransformB; + // apply local offset + aNewTransform.translate(rInfo.mrStartPos.X(), rInfo.mrStartPos.Y()); + + // also apply embedding object's transform + aNewTransform *= rNewTransformB; - // prepare DXArray content. To make it independent from font size (and such from - // the text transformation), scale it to unit coordinates - ::std::vector< double > aDXArray; + // prepare DXArray content. To make it independent from font size (and such from + // the text transformation), scale it to unit coordinates + ::std::vector< double > aDXArray; - if (!rInfo.mpDXArray.empty()) + if (!rInfo.mpDXArray.empty()) + { + aDXArray.reserve(rInfo.mnTextLen); + for(sal_Int32 a=0; a < rInfo.mnTextLen; a++) { - aDXArray.reserve(rInfo.mnTextLen); - for(sal_Int32 a=0; a < rInfo.mnTextLen; a++) - { - aDXArray.push_back(rInfo.mpDXArray[a]); - } + aDXArray.push_back(rInfo.mpDXArray[a]); } + } - OUString caseMappedText = rInfo.mrFont.CalcCaseMap(rInfo.maText); - rtl::Reference<drawinglayer::primitive2d::BasePrimitive2D> pNewPrimitive(buildTextPortionPrimitive(rInfo, caseMappedText, - aFontAttribute, - aDXArray, aNewTransform)); + OUString caseMappedText = rInfo.mrFont.CalcCaseMap(rInfo.maText); + rtl::Reference<drawinglayer::primitive2d::BasePrimitive2D> pNewPrimitive(buildTextPortionPrimitive(rInfo, caseMappedText, + aFontAttribute, + aDXArray, aNewTransform)); - bool bSmallCaps = rInfo.mrFont.IsCapital(); - if (bSmallCaps && rInfo.mpDXArray.empty()) - { - SAL_WARN("svx", "SmallCaps requested with DXArray, abandoning"); - bSmallCaps = false; - } - if (bSmallCaps) + bool bSmallCaps = rInfo.mrFont.IsCapital(); + if (bSmallCaps && rInfo.mpDXArray.empty()) + { + SAL_WARN("svx", "SmallCaps requested with DXArray, abandoning"); + bSmallCaps = false; + } + if (bSmallCaps) + { + // rerun with each sub-portion + DoCapitalsDrawPortionInfo aDoDrawPortionInfo( + rTarget, + rNewTransformA, + rNewTransformB, + rInfo); + rInfo.mrFont.DoOnCapitals(aDoDrawPortionInfo); + + // transfer collected primitives from rTarget to a new container + drawinglayer::primitive2d::Primitive2DContainer aContainer = std::move(rTarget); + + // Take any decoration for the whole formatted portion and keep it to get continuous over/under/strike-through + if (pNewPrimitive->getPrimitive2DID() == PRIMITIVE2D_ID_TEXTDECORATEDPORTIONPRIMITIVE2D) { - // rerun with each sub-portion - DoCapitalsDrawPortionInfo aDoDrawPortionInfo(*this, rInfo); - rInfo.mrFont.DoOnCapitals(aDoDrawPortionInfo); - - // transfer collected primitives from maTextPortionPrimitives to a new container - drawinglayer::primitive2d::Primitive2DContainer aContainer = std::move(maTextPortionPrimitives); + const drawinglayer::primitive2d::TextDecoratedPortionPrimitive2D* pTCPP = + static_cast<const drawinglayer::primitive2d::TextDecoratedPortionPrimitive2D*>(pNewPrimitive.get()); - // Take any decoration for the whole formatted portion and keep it to get continuous over/under/strike-through - if (pNewPrimitive->getPrimitive2DID() == PRIMITIVE2D_ID_TEXTDECORATEDPORTIONPRIMITIVE2D) + if (pTCPP->getWordLineMode()) // single word mode: 'Individual words' in UI { - const drawinglayer::primitive2d::TextDecoratedPortionPrimitive2D* pTCPP = - static_cast<const drawinglayer::primitive2d::TextDecoratedPortionPrimitive2D*>(pNewPrimitive.get()); - - if (pTCPP->getWordLineMode()) // single word mode: 'Individual words' in UI - { - // Split to single word primitives using TextBreakupHelper - drawinglayer::primitive2d::TextBreakupHelper aTextBreakupHelper(*pTCPP); - drawinglayer::primitive2d::Primitive2DContainer aBroken(aTextBreakupHelper.extractResult(drawinglayer::primitive2d::BreakupUnit::Word)); - for (auto& rPortion : aBroken) - { - assert(rPortion->getPrimitive2DID() == PRIMITIVE2D_ID_TEXTDECORATEDPORTIONPRIMITIVE2D && - "TextBreakupHelper generates same output primitive type as input"); - - const drawinglayer::primitive2d::TextDecoratedPortionPrimitive2D* pPortion = - static_cast<const drawinglayer::primitive2d::TextDecoratedPortionPrimitive2D*>(rPortion.get()); - - // create and add decoration - const drawinglayer::primitive2d::Primitive2DContainer& rDecorationGeometryContent( - pPortion->getOrCreateDecorationGeometryContent( - pPortion->getTextTransform(), - caseMappedText, - pPortion->getTextPosition(), - pPortion->getTextLength(), - pPortion->getDXArray())); - - aContainer.insert(aContainer.end(), rDecorationGeometryContent.begin(), rDecorationGeometryContent.end()); - } - } - else + // Split to single word primitives using TextBreakupHelper + drawinglayer::primitive2d::TextBreakupHelper aTextBreakupHelper(*pTCPP); + drawinglayer::primitive2d::Primitive2DContainer aBroken(aTextBreakupHelper.extractResult(drawinglayer::primitive2d::BreakupUnit::Word)); + for (auto& rPortion : aBroken) { + assert(rPortion->getPrimitive2DID() == PRIMITIVE2D_ID_TEXTDECORATEDPORTIONPRIMITIVE2D && + "TextBreakupHelper generates same output primitive type as input"); + + const drawinglayer::primitive2d::TextDecoratedPortionPrimitive2D* pPortion = + static_cast<const drawinglayer::primitive2d::TextDecoratedPortionPrimitive2D*>(rPortion.get()); + // create and add decoration const drawinglayer::primitive2d::Primitive2DContainer& rDecorationGeometryContent( - pTCPP->getOrCreateDecorationGeometryContent( - pTCPP->getTextTransform(), + pPortion->getOrCreateDecorationGeometryContent( + pPortion->getTextTransform(), caseMappedText, - rInfo.mnTextStart, - rInfo.mnTextLen, - aDXArray)); + pPortion->getTextPosition(), + pPortion->getTextLength(), + pPortion->getDXArray())); aContainer.insert(aContainer.end(), rDecorationGeometryContent.begin(), rDecorationGeometryContent.end()); } } - - pNewPrimitive = new drawinglayer::primitive2d::GroupPrimitive2D(std::move(aContainer)); + else + { + // create and add decoration + const drawinglayer::primitive2d::Primitive2DContainer& rDecorationGeometryContent( + pTCPP->getOrCreateDecorationGeometryContent( + pTCPP->getTextTransform(), + caseMappedText, + rInfo.mnTextStart, + rInfo.mnTextLen, + aDXArray)); + + aContainer.insert(aContainer.end(), rDecorationGeometryContent.begin(), rDecorationGeometryContent.end()); + } } - const Color aFontColor(rInfo.mrFont.GetColor()); - if (aFontColor.IsTransparent()) - { - // Handle semi-transparent text for both the decorated and simple case here. - pNewPrimitive = new drawinglayer::primitive2d::UnifiedTransparencePrimitive2D( - drawinglayer::primitive2d::Primitive2DContainer{ pNewPrimitive }, - (255 - aFontColor.GetAlpha()) / 255.0); - } + pNewPrimitive = new drawinglayer::primitive2d::GroupPrimitive2D(std::move(aContainer)); + } - if(rInfo.mbEndOfBullet) - { - // embed in TextHierarchyBulletPrimitive2D - drawinglayer::primitive2d::Primitive2DContainer aNewSequence { pNewPrimitive }; - pNewPrimitive = new drawinglayer::primitive2d::TextHierarchyBulletPrimitive2D(std::move(aNewSequence)); - } + const Color aFontColor(rInfo.mrFont.GetColor()); + if (aFontColor.IsTransparent()) + { + // Handle semi-transparent text for both the decorated and simple case here. + pNewPrimitive = new drawinglayer::primitive2d::UnifiedTransparencePrimitive2D( + drawinglayer::primitive2d::Primitive2DContainer{ pNewPrimitive }, + (255 - aFontColor.GetAlpha()) / 255.0); + } - if(rInfo.mpFieldData) - { - pNewPrimitive = impCheckFieldPrimitive(pNewPrimitive.get(), rInfo); - } + if(rInfo.mbEndOfBullet) + { + // embed in TextHierarchyBulletPrimitive2D + drawinglayer::primitive2d::Primitive2DContainer aNewSequence { pNewPrimitive }; + pNewPrimitive = new drawinglayer::primitive2d::TextHierarchyBulletPrimitive2D(std::move(aNewSequence)); + } - maTextPortionPrimitives.push_back(pNewPrimitive); + if(rInfo.mpFieldData) + { + pNewPrimitive = CheckFieldPrimitive(pNewPrimitive.get(), rInfo); + } + + rTarget.push_back(pNewPrimitive); - // support for WrongSpellVector. Create WrongSpellPrimitives as needed - if(!rInfo.mpWrongSpellVector || aDXArray.empty()) - return; + // support for WrongSpellVector. Create WrongSpellPrimitives as needed + if(!rInfo.mpWrongSpellVector || aDXArray.empty()) + return; - const sal_Int32 nSize(rInfo.mpWrongSpellVector->size()); - const sal_Int32 nDXCount(aDXArray.size()); - const basegfx::BColor aSpellColor(1.0, 0.0, 0.0); // red, hard coded + const sal_Int32 nSize(rInfo.mpWrongSpellVector->size()); + const sal_Int32 nDXCount(aDXArray.size()); + const basegfx::BColor aSpellColor(1.0, 0.0, 0.0); // red, hard coded + + for(sal_Int32 a(0); a < nSize; a++) + { + const EEngineData::WrongSpellClass& rCandidate = (*rInfo.mpWrongSpellVector)[a]; - for(sal_Int32 a(0); a < nSize; a++) + if(rCandidate.nStart >= rInfo.mnTextStart && rCandidate.nEnd >= rInfo.mnTextStart && rCandidate.nEnd > rCandidate.nStart) { - const EEngineData::WrongSpellClass& rCandidate = (*rInfo.mpWrongSpellVector)[a]; + const sal_Int32 nStart(rCandidate.nStart - rInfo.mnTextStart); + const sal_Int32 nEnd(rCandidate.nEnd - rInfo.mnTextStart); + double fStart(0.0); + double fEnd(0.0); - if(rCandidate.nStart >= rInfo.mnTextStart && rCandidate.nEnd >= rInfo.mnTextStart && rCandidate.nEnd > rCandidate.nStart) + if(nStart > 0 && nStart - 1 < nDXCount) { - const sal_Int32 nStart(rCandidate.nStart - rInfo.mnTextStart); - const sal_Int32 nEnd(rCandidate.nEnd - rInfo.mnTextStart); - double fStart(0.0); - double fEnd(0.0); + fStart = aDXArray[nStart - 1]; + } - if(nStart > 0 && nStart - 1 < nDXCount) + if(nEnd > 0 && nEnd - 1 < nDXCount) + { + fEnd = aDXArray[nEnd - 1]; + } + + if(!basegfx::fTools::equal(fStart, fEnd)) + { + if(rInfo.IsRTL()) { - fStart = aDXArray[nStart - 1]; + // #i98523# + // When the portion is RTL, mirror the redlining using the + // full portion width + const double fTextWidth(aDXArray[aDXArray.size() - 1]); + + fStart = fTextWidth - fStart; + fEnd = fTextWidth - fEnd; } - if(nEnd > 0 && nEnd - 1 < nDXCount) + // need to take FontScaling out of values; it's already part of + // aNewTransform and would be double applied + const double fFontScaleX(aFontScaling.getX() * fPropFontFactor); + + if(!basegfx::fTools::equal(fFontScaleX, 1.0) + && !basegfx::fTools::equalZero(fFontScaleX)) { - fEnd = aDXArray[nEnd - 1]; + fStart /= fFontScaleX; + fEnd /= fFontScaleX; } - if(!basegfx::fTools::equal(fStart, fEnd)) - { - if(rInfo.IsRTL()) - { - // #i98523# - // When the portion is RTL, mirror the redlining using the - // full portion width - const double fTextWidth(aDXArray[aDXArray.size() - 1]); + rTarget.push_back(new drawinglayer::primitive2d::WrongSpellPrimitive2D( + aNewTransform, + fStart, + fEnd, + aSpellColor)); + } + } + } +} + +void CreateDrawBulletPrimitivesFromDrawBulletInfo( + drawinglayer::primitive2d::Primitive2DContainer& rTarget, + const basegfx::B2DHomMatrix& rNewTransformA, + const basegfx::B2DHomMatrix& rNewTransformB, + const DrawBulletInfo& rInfo) +{ + basegfx::B2DHomMatrix aNewTransform; + + // add size to new transform + aNewTransform.scale(rInfo.maBulletSize.getWidth(), rInfo.maBulletSize.getHeight()); + + // apply transformA + aNewTransform *= rNewTransformA; + + // apply local offset + aNewTransform.translate(rInfo.maBulletPosition.X(), rInfo.maBulletPosition.Y()); + + // also apply embedding object's transform + aNewTransform *= rNewTransformB; + + // prepare empty GraphicAttr + const GraphicAttr aGraphicAttr; + + // create GraphicPrimitive2D + const drawinglayer::primitive2d::Primitive2DReference aNewReference(new drawinglayer::primitive2d::GraphicPrimitive2D( + aNewTransform, + rInfo.maBulletGraphicObject, + aGraphicAttr)); + + // embed in TextHierarchyBulletPrimitive2D + drawinglayer::primitive2d::Primitive2DContainer aNewSequence { aNewReference }; + rtl::Reference<drawinglayer::primitive2d::BasePrimitive2D> pNewPrimitive = new drawinglayer::primitive2d::TextHierarchyBulletPrimitive2D(std::move(aNewSequence)); + + // add to output + rTarget.push_back(pNewPrimitive); +} + +namespace +{ + class impTextBreakupHandler + { + private: + drawinglayer::primitive2d::Primitive2DContainer maTextPortionPrimitives; + drawinglayer::primitive2d::Primitive2DContainer maLinePrimitives; + drawinglayer::primitive2d::Primitive2DContainer maParagraphPrimitives; + + SdrOutliner& mrOutliner; + basegfx::B2DHomMatrix maNewTransformA; + basegfx::B2DHomMatrix maNewTransformB; + + // the visible area for contour text decomposition + basegfx::B2DVector maScale; + + // ClipRange for BlockText decomposition; only text portions completely + // inside are to be accepted, so this is different from geometric clipping + // (which would allow e.g. upper parts of portions to remain). Only used for + // BlockText (see there) + basegfx::B2DRange maClipRange; + + void impFlushTextPortionPrimitivesToLinePrimitives(); + void impFlushLinePrimitivesToParagraphPrimitives(sal_Int32 nPara); + void impHandleDrawPortionInfo(const DrawPortionInfo& rInfo); + void impHandleDrawBulletInfo(const DrawBulletInfo& rInfo); + + public: + explicit impTextBreakupHandler(SdrOutliner& rOutliner) + : mrOutliner(rOutliner) + { + } - fStart = fTextWidth - fStart; - fEnd = fTextWidth - fEnd; + void decomposeContourTextPrimitive(const basegfx::B2DHomMatrix& rNewTransformA, const basegfx::B2DHomMatrix& rNewTransformB, const basegfx::B2DVector& rScale) + { + maScale = rScale; + maNewTransformA = rNewTransformA; + maNewTransformB = rNewTransformB; + + mrOutliner.StripPortions( + [this](const DrawPortionInfo& rInfo){ + // for contour text, ignore (clip away) all portions which are below + // the visible area given by maScale + if(static_cast<double>(rInfo.mrStartPos.Y()) < maScale.getY()) + { + impHandleDrawPortionInfo(rInfo); } + }, + [this](const DrawBulletInfo& rInfo){ impHandleDrawBulletInfo(rInfo); }); + } - // need to take FontScaling out of values; it's already part of - // aNewTransform and would be double applied - const double fFontScaleX(aFontScaling.getX() * fPropFontFactor); + void decomposeBlockTextPrimitive( + const basegfx::B2DHomMatrix& rNewTransformA, + const basegfx::B2DHomMatrix& rNewTransformB, + const basegfx::B2DRange& rClipRange) + { + maNewTransformA = rNewTransformA; + maNewTransformB = rNewTransformB; + maClipRange = rClipRange; - if(!basegfx::fTools::equal(fFontScaleX, 1.0) - && !basegfx::fTools::equalZero(fFontScaleX)) + mrOutliner.StripPortions( + [this](const DrawPortionInfo& rInfo){ + // Is clipping wanted? This is text clipping; only accept a portion + // if it's completely in the range + if(!maClipRange.isEmpty()) { - fStart /= fFontScaleX; - fEnd /= fFontScaleX; + // Test start position first; this allows to not get the text range at + // all if text is far outside + const basegfx::B2DPoint aStartPosition(rInfo.mrStartPos.X(), rInfo.mrStartPos.Y()); + + if(!maClipRange.isInside(aStartPosition)) + { + return; + } + + // Start position is inside. Get TextBoundRect and TopLeft next + drawinglayer::primitive2d::TextLayouterDevice aTextLayouterDevice; + aTextLayouterDevice.setFont(rInfo.mrFont); + + const basegfx::B2DRange aTextBoundRect( + aTextLayouterDevice.getTextBoundRect( + rInfo.maText, rInfo.mnTextStart, rInfo.mnTextLen)); + const basegfx::B2DPoint aTopLeft(aTextBoundRect.getMinimum() + aStartPosition); + + if(!maClipRange.isInside(aTopLeft)) + { + return; + } + + // TopLeft is inside. Get BottomRight and check + const basegfx::B2DPoint aBottomRight(aTextBoundRect.getMaximum() + aStartPosition); + + if(!maClipRange.isInside(aBottomRight)) + { + return; + } + + // all inside, clip was successful } + impHandleDrawPortionInfo(rInfo); + }, + [this](const DrawBulletInfo& rInfo){ impHandleDrawBulletInfo(rInfo); }); + } - maTextPortionPrimitives.push_back(new drawinglayer::primitive2d::WrongSpellPrimitive2D( - aNewTransform, - fStart, - fEnd, - aSpellColor)); - } - } + void decomposeStretchTextPrimitive(const basegfx::B2DHomMatrix& rNewTransformA, const basegfx::B2DHomMatrix& rNewTransformB) + { + maNewTransformA = rNewTransformA; + maNewTransformB = rNewTransformB; + + mrOutliner.StripPortions( + [this](const DrawPortionInfo& rInfo){ impHandleDrawPortionInfo(rInfo); }, + [this](const DrawBulletInfo& rInfo){ impHandleDrawBulletInfo(rInfo); }); } - } + + drawinglayer::primitive2d::Primitive2DContainer extractPrimitive2DSequence(); + }; rtl::Reference<drawinglayer::primitive2d::BasePrimitive2D> buildTextPortionPrimitive( const DrawPortionInfo& rInfo, const OUString& rText, @@ -598,50 +734,6 @@ namespace return pNewPrimitive; } - rtl::Reference<drawinglayer::primitive2d::BasePrimitive2D> impTextBreakupHandler::impCheckFieldPrimitive(drawinglayer::primitive2d::BasePrimitive2D* pPrimitive, const DrawPortionInfo& rInfo) - { - rtl::Reference<drawinglayer::primitive2d::BasePrimitive2D> xRet = pPrimitive; - if(rInfo.mpFieldData) - { - // Support for FIELD_SEQ_BEGIN, FIELD_SEQ_END. If used, create a TextHierarchyFieldPrimitive2D - // which holds the field type and, if applicable, the URL - const SvxURLField* pURLField = dynamic_cast< const SvxURLField* >(rInfo.mpFieldData); - const SvxPageField* pPageField = dynamic_cast< const SvxPageField* >(rInfo.mpFieldData); - - // embed current primitive to a sequence - drawinglayer::primitive2d::Primitive2DContainer aSequence; - - if(pPrimitive) - { - aSequence.resize(1); - aSequence[0] = drawinglayer::primitive2d::Primitive2DReference(pPrimitive); - } - - if(pURLField) - { - // extended this to hold more of the contents of the original - // SvxURLField since that stuff is still used in HitTest and e.g. Calc - std::vector< std::pair< OUString, OUString>> meValues; - meValues.emplace_back("URL", pURLField->GetURL()); - meValues.emplace_back("Representation", pURLField->GetRepresentation()); - meValues.emplace_back("TargetFrame", pURLField->GetTargetFrame()); - meValues.emplace_back("AltText", pURLField->GetName()); - meValues.emplace_back("SvxURLFormat", OUString::number(static_cast<sal_uInt16>(pURLField->GetFormat()))); - xRet = new drawinglayer::primitive2d::TextHierarchyFieldPrimitive2D(std::move(aSequence), drawinglayer::primitive2d::FIELD_TYPE_URL, &meValues); - } - else if(pPageField) - { - xRet = new drawinglayer::primitive2d::TextHierarchyFieldPrimitive2D(std::move(aSequence), drawinglayer::primitive2d::FIELD_TYPE_PAGE); - } - else - { - xRet = new drawinglayer::primitive2d::TextHierarchyFieldPrimitive2D(std::move(aSequence), drawinglayer::primitive2d::FIELD_TYPE_COMMON); - } - } - - return xRet; - } - void impTextBreakupHandler::impFlushTextPortionPrimitivesToLinePrimitives() { // only create a line primitive when we had content; there is no need for @@ -671,7 +763,11 @@ namespace void impTextBreakupHandler::impHandleDrawPortionInfo(const DrawPortionInfo& rInfo) { - impCreateTextPortionPrimitive(rInfo); + CreateTextPortionPrimitivesFromDrawPortionInfo( + maTextPortionPrimitives, + maNewTransformA, + maNewTransformB, + rInfo); if(rInfo.mbEndOfLine || rInfo.mbEndOfParagraph) { @@ -686,6 +782,11 @@ namespace void impTextBreakupHandler::impHandleDrawBulletInfo(const DrawBulletInfo& rInfo) { + CreateDrawBulletPrimitivesFromDrawBulletInfo( + maTextPortionPrimitives, + maNewTransformA, + maNewTransformB, + rInfo); basegfx::B2DHomMatrix aNewTransform; // add size to new transform @@ -717,93 +818,6 @@ namespace maTextPortionPrimitives.push_back(pNewPrimitive); } - IMPL_LINK(impTextBreakupHandler, decomposeContourTextPrimitive, DrawPortionInfo*, pInfo, void) - { - // for contour text, ignore (clip away) all portions which are below - // the visible area given by maScale - if(pInfo && static_cast<double>(pInfo->mrStartPos.Y()) < maScale.getY()) - { - impHandleDrawPortionInfo(*pInfo); - } - } - - IMPL_LINK(impTextBreakupHandler, decomposeBlockTextPrimitive, DrawPortionInfo*, pInfo, void) - { - if(!pInfo) - return; - - // Is clipping wanted? This is text clipping; only accept a portion - // if it's completely in the range - if(!maClipRange.isEmpty()) - { - // Test start position first; this allows to not get the text range at - // all if text is far outside - const basegfx::B2DPoint aStartPosition(pInfo->mrStartPos.X(), pInfo->mrStartPos.Y()); - - if(!maClipRange.isInside(aStartPosition)) - { - return; - } - - // Start position is inside. Get TextBoundRect and TopLeft next - drawinglayer::primitive2d::TextLayouterDevice aTextLayouterDevice; - aTextLayouterDevice.setFont(pInfo->mrFont); - - const basegfx::B2DRange aTextBoundRect( - aTextLayouterDevice.getTextBoundRect( - pInfo->maText, pInfo->mnTextStart, pInfo->mnTextLen)); - const basegfx::B2DPoint aTopLeft(aTextBoundRect.getMinimum() + aStartPosition); - - if(!maClipRange.isInside(aTopLeft)) - { - return; - } - - // TopLeft is inside. Get BottomRight and check - const basegfx::B2DPoint aBottomRight(aTextBoundRect.getMaximum() + aStartPosition); - - if(!maClipRange.isInside(aBottomRight)) - { - return; - } - - // all inside, clip was successful - } - impHandleDrawPortionInfo(*pInfo); - } - - IMPL_LINK(impTextBreakupHandler, decomposeStretchTextPrimitive, DrawPortionInfo*, pInfo, void) - { - if(pInfo) - { - impHandleDrawPortionInfo(*pInfo); - } - } - - IMPL_LINK(impTextBreakupHandler, decomposeContourBulletPrimitive, DrawBulletInfo*, pInfo, void) - { - if(pInfo) - { - impHandleDrawBulletInfo(*pInfo); - } - } - - IMPL_LINK(impTextBreakupHandler, decomposeBlockBulletPrimitive, DrawBulletInfo*, pInfo, void) - { - if(pInfo) - { - impHandleDrawBulletInfo(*pInfo); - } - } - - IMPL_LINK(impTextBreakupHandler, decomposeStretchBulletPrimitive, DrawBulletInfo*, pInfo, void) - { - if(pInfo) - { - impHandleDrawBulletInfo(*pInfo); - } - } - drawinglayer::primitive2d::Primitive2DContainer impTextBreakupHandler::extractPrimitive2DSequence() { if(!maTextPortionPrimitives.empty()) @@ -822,9 +836,7 @@ namespace } } // end of anonymous namespace - // primitive decompositions - void SdrTextObj::impDecomposeContourTextPrimitive( drawinglayer::primitive2d::Primitive2DContainer& rTarget, const drawinglayer::primitive2d::SdrContourTextPrimitive2D& rSdrContourTextPrimitive, diff --git a/svx/source/svdraw/svdotextpathdecomposition.cxx b/svx/source/svdraw/svdotextpathdecomposition.cxx index b33d00880aca..142190a60327 100644 --- a/svx/source/svdraw/svdotextpathdecomposition.cxx +++ b/svx/source/svdraw/svdotextpathdecomposition.cxx @@ -153,8 +153,6 @@ namespace SdrOutliner& mrOutliner; ::std::vector< impPathTextPortion > maPathTextPortions; - DECL_LINK(decompositionPathTextPrimitive, DrawPortionInfo*, void ); - public: explicit impTextBreakupHandler(SdrOutliner& rOutliner) : mrOutliner(rOutliner) @@ -164,8 +162,9 @@ namespace const ::std::vector< impPathTextPortion >& decompositionPathTextPrimitive() { // strip portions to maPathTextPortions - mrOutliner.SetDrawPortionHdl(LINK(this, impTextBreakupHandler, decompositionPathTextPrimitive)); - mrOutliner.StripPortions(); + mrOutliner.StripPortions( + [this](const DrawPortionInfo& rInfo){ maPathTextPortions.emplace_back(rInfo); }, + std::function<void(const DrawBulletInfo&)>()); if(!maPathTextPortions.empty()) { @@ -176,11 +175,6 @@ namespace return maPathTextPortions; } }; - - IMPL_LINK(impTextBreakupHandler, decompositionPathTextPrimitive, DrawPortionInfo*, pInfo, void) - { - maPathTextPortions.emplace_back(*pInfo); - } } // end of anonymous namespace @@ -734,7 +728,6 @@ void SdrTextObj::impDecomposePathTextPrimitive( } // clean up outliner - rOutliner.SetDrawPortionHdl(Link<DrawPortionInfo*,void>()); rOutliner.Clear(); rOutliner.setVisualizedPage(nullptr);
