1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
3 * This file is part of the LibreOffice project.
5 * This Source Code Form is subject to the terms of the Mozilla Public
6 * License, v. 2.0. If a copy of the MPL was not distributed with this
7 * file, You can obtain one at http://mozilla.org/MPL/2.0/.
9 * This file incorporates work covered by the following license notice:
11 * Licensed to the Apache Software Foundation (ASF) under one or more
12 * contributor license agreements. See the NOTICE file distributed
13 * with this work for additional information regarding copyright
14 * ownership. The ASF licenses this file to you under the Apache
15 * License, Version 2.0 (the "License"); you may not use this file
16 * except in compliance with the License. You may obtain a copy of
17 * the License at http://www.apache.org/licenses/LICENSE-2.0 .
21 #include <comphelper/string.hxx>
22 #include <svl/stritem.hxx>
23 #include <svx/svdotext.hxx>
24 #include <svx/svdpage.hxx>
25 #include <svx/svdoutl.hxx>
26 #include <svx/svdmodel.hxx>
27 #include <svx/dialmgr.hxx>
28 #include <svx/strings.hrc>
29 #include <editeng/writingmodeitem.hxx>
30 #include <svx/sdtfchim.hxx>
31 #include <editeng/editdata.hxx>
32 #include <editeng/editstat.hxx>
33 #include <editeng/outlobj.hxx>
34 #include <editeng/editobj.hxx>
35 #include <editeng/outliner.hxx>
36 #include <textchain.hxx>
37 #include <textchainflow.hxx>
38 #include <tools/helpers.hxx>
39 #include <svx/sderitm.hxx>
40 #include <svx/sdooitm.hxx>
41 #include <svx/sdshitm.hxx>
42 #include <svx/sdtagitm.hxx>
43 #include <svx/sdtfsitm.hxx>
44 #include <svx/sdtmfitm.hxx>
45 #include <svx/xtextit0.hxx>
46 #include <svx/compatflags.hxx>
47 #include <sdr/properties/textproperties.hxx>
48 #include <sdr/contact/viewcontactoftextobj.hxx>
49 #include <basegfx/tuple/b2dtuple.hxx>
50 #include <basegfx/matrix/b2dhommatrix.hxx>
51 #include <vcl/gdimtf.hxx>
52 #include <vcl/virdev.hxx>
53 #include <basegfx/matrix/b2dhommatrixtools.hxx>
54 #include <sal/log.hxx>
55 #include <o3tl/unit_conversion.hxx>
56 #include <o3tl/temporary.hxx>
57 #include <unotools/configmgr.hxx>
58 #include <editeng/eeitem.hxx>
59 #include <editeng/fhgtitem.hxx>
61 using namespace com::sun::star
;
63 // BaseProperties section
64 std::unique_ptr
<sdr::properties::BaseProperties
> SdrTextObj::CreateObjectSpecificProperties()
66 return std::make_unique
<sdr::properties::TextProperties
>(*this);
69 // DrawContact section
70 std::unique_ptr
<sdr::contact::ViewContact
> SdrTextObj::CreateObjectSpecificViewContact()
72 return std::make_unique
<sdr::contact::ViewContactOfTextObj
>(*this);
75 SdrTextObj::SdrTextObj(SdrModel
& rSdrModel
)
76 : SdrAttrObj(rSdrModel
)
77 , mpEditingOutliner(nullptr)
78 , meTextKind(SdrObjKind::Text
)
79 , maTextEditOffset(Point(0, 0))
82 , mbTextSizeDirty(false)
84 , mbDisableAutoWidthOnDragging(false)
85 , mbTextAnimationAllowed(true)
86 , mbInDownScale(false)
89 mbSupportTextIndentingOnLineWidthChange
= true;
92 SdrTextObj::SdrTextObj(SdrModel
& rSdrModel
, SdrTextObj
const & rSource
)
93 : SdrAttrObj(rSdrModel
, rSource
)
94 , mpEditingOutliner(nullptr)
95 , meTextKind(rSource
.meTextKind
)
96 , maTextEditOffset(Point(0, 0))
97 , mbTextFrame(rSource
.mbTextFrame
)
98 , mbNoShear(rSource
.mbNoShear
)
99 , mbTextSizeDirty(rSource
.mbTextSizeDirty
)
100 , mbInEditMode(false)
101 , mbDisableAutoWidthOnDragging(rSource
.mbDisableAutoWidthOnDragging
)
102 , mbTextAnimationAllowed(true)
103 , mbInDownScale(false)
106 mbSupportTextIndentingOnLineWidthChange
= true;
108 maRectangle
= rSource
.maRectangle
;
109 maGeo
= rSource
.maGeo
;
110 maTextSize
= rSource
.maTextSize
;
112 // Not all of the necessary parameters were copied yet.
113 SdrText
* pText
= getActiveText();
115 if( pText
&& rSource
.HasText() )
117 // before pNewOutlinerParaObject was created the same, but
118 // set at mpText (outside this scope), but mpText might be
119 // empty (this operator== seems not prepared for MultiText
120 // objects). In the current form it makes only sense to
121 // create locally and use locally on a known existing SdrText
122 const Outliner
* pEO
= rSource
.mpEditingOutliner
;
123 std::optional
<OutlinerParaObject
> pNewOutlinerParaObject
;
127 pNewOutlinerParaObject
= pEO
->CreateParaObject();
129 else if (nullptr != rSource
.getActiveText()->GetOutlinerParaObject())
131 pNewOutlinerParaObject
= *rSource
.getActiveText()->GetOutlinerParaObject();
134 pText
->SetOutlinerParaObject( std::move(pNewOutlinerParaObject
) );
137 ImpSetTextStyleSheetListeners();
140 SdrTextObj::SdrTextObj(SdrModel
& rSdrModel
, const tools::Rectangle
& rNewRect
)
141 : SdrAttrObj(rSdrModel
)
142 , mpEditingOutliner(nullptr)
143 , meTextKind(SdrObjKind::Text
)
144 , maTextEditOffset(Point(0, 0))
147 , mbTextSizeDirty(false)
148 , mbInEditMode(false)
149 , mbDisableAutoWidthOnDragging(false)
150 , mbTextAnimationAllowed(true)
151 , mbInDownScale(false)
153 tools::Rectangle
aRectangle(rNewRect
);
154 ImpJustifyRect(aRectangle
);
155 setRectangle(aRectangle
);
158 mbSupportTextIndentingOnLineWidthChange
= true;
161 SdrTextObj::SdrTextObj(SdrModel
& rSdrModel
, SdrObjKind eNewTextKind
)
162 : SdrAttrObj(rSdrModel
)
163 , mpEditingOutliner(nullptr)
164 , meTextKind(eNewTextKind
)
165 , maTextEditOffset(Point(0, 0))
168 , mbTextSizeDirty(false)
169 , mbInEditMode(false)
170 , mbDisableAutoWidthOnDragging(false)
171 , mbTextAnimationAllowed(true)
172 , mbInDownScale(false)
175 mbSupportTextIndentingOnLineWidthChange
= true;
178 SdrTextObj::SdrTextObj(SdrModel
& rSdrModel
, SdrObjKind eNewTextKind
,
179 const tools::Rectangle
& rNewRect
)
180 : SdrAttrObj(rSdrModel
)
181 , mpEditingOutliner(nullptr)
182 , meTextKind(eNewTextKind
)
183 , maTextEditOffset(Point(0, 0))
186 , mbTextSizeDirty(false)
187 , mbInEditMode(false)
188 , mbDisableAutoWidthOnDragging(false)
189 , mbTextAnimationAllowed(true)
190 , mbInDownScale(false)
192 tools::Rectangle
aRectangle(rNewRect
);
193 ImpJustifyRect(aRectangle
);
194 setRectangle(aRectangle
);
197 mbSupportTextIndentingOnLineWidthChange
= true;
200 SdrTextObj::~SdrTextObj()
206 void SdrTextObj::FitFrameToTextSize()
208 ImpJustifyRect(maRectangle
);
210 SdrText
* pText
= getActiveText();
211 if(pText
==nullptr || !pText
->GetOutlinerParaObject())
214 SdrOutliner
& rOutliner
=ImpGetDrawOutliner();
215 rOutliner
.SetPaperSize(Size(getRectangle().Right() - getRectangle().Left(), getRectangle().Bottom() - getRectangle().Top()));
216 rOutliner
.SetUpdateLayout(true);
217 rOutliner
.SetText(*pText
->GetOutlinerParaObject());
218 Size
aNewSize(rOutliner
.CalcTextSize());
220 aNewSize
.AdjustWidth( 1 ); // because of possible rounding errors
221 aNewSize
.AdjustWidth(GetTextLeftDistance()+GetTextRightDistance() );
222 aNewSize
.AdjustHeight(GetTextUpperDistance()+GetTextLowerDistance() );
223 tools::Rectangle
aNewRect(getRectangle());
224 aNewRect
.SetSize(aNewSize
);
225 ImpJustifyRect(aNewRect
);
227 if (aNewRect
!= getRectangle())
228 SetLogicRect(aNewRect
);
231 void SdrTextObj::NbcSetText(const OUString
& rStr
)
233 SdrOutliner
& rOutliner
=ImpGetDrawOutliner();
234 rOutliner
.SetStyleSheet( 0, GetStyleSheet());
235 rOutliner
.SetText(rStr
,rOutliner
.GetParagraph( 0 ));
236 std::optional
<OutlinerParaObject
> pNewText
=rOutliner
.CreateParaObject();
237 NbcSetOutlinerParaObject(std::move(pNewText
));
238 mbTextSizeDirty
=true;
241 void SdrTextObj::SetText(const OUString
& rStr
)
243 tools::Rectangle aBoundRect0
; if (m_pUserCall
!=nullptr) aBoundRect0
=GetLastBoundRect();
246 BroadcastObjectChange();
247 SendUserCall(SdrUserCallType::Resize
,aBoundRect0
);
250 void SdrTextObj::NbcSetText(SvStream
& rInput
, const OUString
& rBaseURL
, EETextFormat eFormat
)
252 SdrOutliner
& rOutliner
=ImpGetDrawOutliner();
253 rOutliner
.SetStyleSheet( 0, GetStyleSheet());
254 rOutliner
.Read(rInput
,rBaseURL
,eFormat
);
255 std::optional
<OutlinerParaObject
> pNewText
=rOutliner
.CreateParaObject();
256 rOutliner
.SetUpdateLayout(true);
257 Size
aSize(rOutliner
.CalcTextSize());
259 NbcSetOutlinerParaObject(std::move(pNewText
));
261 mbTextSizeDirty
=false;
264 void SdrTextObj::SetText(SvStream
& rInput
, const OUString
& rBaseURL
, EETextFormat eFormat
)
266 tools::Rectangle aBoundRect0
; if (m_pUserCall
!=nullptr) aBoundRect0
=GetLastBoundRect();
267 NbcSetText(rInput
,rBaseURL
,eFormat
);
269 BroadcastObjectChange();
270 SendUserCall(SdrUserCallType::Resize
,aBoundRect0
);
273 const Size
& SdrTextObj::GetTextSize() const
278 SdrText
* pText
= getActiveText();
279 if( pText
&& pText
->GetOutlinerParaObject ())
281 SdrOutliner
& rOutliner
=ImpGetDrawOutliner();
282 rOutliner
.SetText(*pText
->GetOutlinerParaObject());
283 rOutliner
.SetUpdateLayout(true);
284 aSiz
=rOutliner
.CalcTextSize();
287 // casting to nonconst twice
288 const_cast<SdrTextObj
*>(this)->maTextSize
= aSiz
;
289 const_cast<SdrTextObj
*>(this)->mbTextSizeDirty
= false;
294 bool SdrTextObj::IsAutoGrowHeight() const
297 return false; // AutoGrow only together with TextFrames
299 const SfxItemSet
& rSet
= GetObjectItemSet();
300 bool bRet
= rSet
.Get(SDRATTR_TEXT_AUTOGROWHEIGHT
).GetValue();
304 SdrTextAniKind eAniKind
= rSet
.Get(SDRATTR_TEXT_ANIKIND
).GetValue();
306 if(eAniKind
== SdrTextAniKind::Scroll
|| eAniKind
== SdrTextAniKind::Alternate
|| eAniKind
== SdrTextAniKind::Slide
)
308 SdrTextAniDirection eDirection
= rSet
.Get(SDRATTR_TEXT_ANIDIRECTION
).GetValue();
310 if(eDirection
== SdrTextAniDirection::Up
|| eDirection
== SdrTextAniDirection::Down
)
319 bool SdrTextObj::IsAutoGrowWidth() const
322 return false; // AutoGrow only together with TextFrames
324 const SfxItemSet
& rSet
= GetObjectItemSet();
325 bool bRet
= rSet
.Get(SDRATTR_TEXT_AUTOGROWWIDTH
).GetValue();
327 bool bInEditMOde
= IsInEditMode();
329 if(!bInEditMOde
&& bRet
)
331 SdrTextAniKind eAniKind
= rSet
.Get(SDRATTR_TEXT_ANIKIND
).GetValue();
333 if(eAniKind
== SdrTextAniKind::Scroll
|| eAniKind
== SdrTextAniKind::Alternate
|| eAniKind
== SdrTextAniKind::Slide
)
335 SdrTextAniDirection eDirection
= rSet
.Get(SDRATTR_TEXT_ANIDIRECTION
).GetValue();
337 if(eDirection
== SdrTextAniDirection::Left
|| eDirection
== SdrTextAniDirection::Right
)
346 SdrTextHorzAdjust
SdrTextObj::GetTextHorizontalAdjust() const
348 return GetTextHorizontalAdjust(GetObjectItemSet());
351 SdrTextHorzAdjust
SdrTextObj::GetTextHorizontalAdjust(const SfxItemSet
& rSet
) const
353 if(IsContourTextFrame())
354 return SDRTEXTHORZADJUST_BLOCK
;
356 SdrTextHorzAdjust eRet
= rSet
.Get(SDRATTR_TEXT_HORZADJUST
).GetValue();
358 bool bInEditMode
= IsInEditMode();
360 if(!bInEditMode
&& eRet
== SDRTEXTHORZADJUST_BLOCK
)
362 SdrTextAniKind eAniKind
= rSet
.Get(SDRATTR_TEXT_ANIKIND
).GetValue();
364 if(eAniKind
== SdrTextAniKind::Scroll
|| eAniKind
== SdrTextAniKind::Alternate
|| eAniKind
== SdrTextAniKind::Slide
)
366 SdrTextAniDirection eDirection
= rSet
.Get(SDRATTR_TEXT_ANIDIRECTION
).GetValue();
368 if(eDirection
== SdrTextAniDirection::Left
|| eDirection
== SdrTextAniDirection::Right
)
370 eRet
= SDRTEXTHORZADJUST_LEFT
;
376 } // defaults: BLOCK (justify) for text frame, CENTER for captions of drawing objects
378 SdrTextVertAdjust
SdrTextObj::GetTextVerticalAdjust() const
380 return GetTextVerticalAdjust(GetObjectItemSet());
383 SdrTextVertAdjust
SdrTextObj::GetTextVerticalAdjust(const SfxItemSet
& rSet
) const
385 if(IsContourTextFrame())
386 return SDRTEXTVERTADJUST_TOP
;
388 // Take care for vertical text animation here
389 SdrTextVertAdjust eRet
= rSet
.Get(SDRATTR_TEXT_VERTADJUST
).GetValue();
390 bool bInEditMode
= IsInEditMode();
392 // Take care for vertical text animation here
393 if(!bInEditMode
&& eRet
== SDRTEXTVERTADJUST_BLOCK
)
395 SdrTextAniKind eAniKind
= rSet
.Get(SDRATTR_TEXT_ANIKIND
).GetValue();
397 if(eAniKind
== SdrTextAniKind::Scroll
|| eAniKind
== SdrTextAniKind::Alternate
|| eAniKind
== SdrTextAniKind::Slide
)
399 SdrTextAniDirection eDirection
= rSet
.Get(SDRATTR_TEXT_ANIDIRECTION
).GetValue();
401 if(eDirection
== SdrTextAniDirection::Left
|| eDirection
== SdrTextAniDirection::Right
)
403 eRet
= SDRTEXTVERTADJUST_TOP
;
409 } // defaults: TOP for text frame, CENTER for captions of drawing objects
411 void SdrTextObj::ImpJustifyRect(tools::Rectangle
& rRect
)
413 if (!rRect
.IsEmpty()) {
415 if (rRect
.Left()==rRect
.Right()) rRect
.AdjustRight( 1 );
416 if (rRect
.Top()==rRect
.Bottom()) rRect
.AdjustBottom( 1 );
420 void SdrTextObj::ImpCheckShear()
422 if (mbNoShear
&& maGeo
.m_nShearAngle
)
424 maGeo
.m_nShearAngle
= 0_deg100
;
425 maGeo
.mfTanShearAngle
= 0;
429 void SdrTextObj::TakeObjInfo(SdrObjTransformInfoRec
& rInfo
) const
431 bool bNoTextFrame
=!IsTextFrame();
432 rInfo
.bResizeFreeAllowed
=bNoTextFrame
|| ((maGeo
.m_nRotationAngle
.get() % 9000) == 0);
433 rInfo
.bResizePropAllowed
=true;
434 rInfo
.bRotateFreeAllowed
=true;
435 rInfo
.bRotate90Allowed
=true;
436 rInfo
.bMirrorFreeAllowed
=bNoTextFrame
;
437 rInfo
.bMirror45Allowed
=bNoTextFrame
;
438 rInfo
.bMirror90Allowed
=bNoTextFrame
;
440 // allow transparency
441 rInfo
.bTransparenceAllowed
= true;
443 rInfo
.bShearAllowed
=bNoTextFrame
;
444 rInfo
.bEdgeRadiusAllowed
=true;
445 bool bCanConv
=ImpCanConvTextToCurve();
446 rInfo
.bCanConvToPath
=bCanConv
;
447 rInfo
.bCanConvToPoly
=bCanConv
;
448 rInfo
.bCanConvToPathLineToArea
=bCanConv
;
449 rInfo
.bCanConvToPolyLineToArea
=bCanConv
;
450 rInfo
.bCanConvToContour
= (rInfo
.bCanConvToPoly
|| LineGeometryUsageIsNecessary());
453 SdrObjKind
SdrTextObj::GetObjIdentifier() const
458 bool SdrTextObj::HasTextImpl( SdrOutliner
const * pOutliner
)
463 Paragraph
* p1stPara
=pOutliner
->GetParagraph( 0 );
464 sal_Int32 nParaCount
=pOutliner
->GetParagraphCount();
465 if(p1stPara
==nullptr)
470 // if it is only one paragraph, check if that paragraph is empty
471 if( pOutliner
->GetText(p1stPara
).isEmpty() )
480 void SdrTextObj::handlePageChange(SdrPage
* pOldPage
, SdrPage
* pNewPage
)
482 const bool bRemove(pNewPage
== nullptr && pOldPage
!= nullptr);
483 const bool bInsert(pNewPage
!= nullptr && pOldPage
== nullptr);
484 const bool bLinked(IsLinkedText());
486 if (bLinked
&& bRemove
)
492 SdrAttrObj::handlePageChange(pOldPage
, pNewPage
);
494 if (bLinked
&& bInsert
)
500 void SdrTextObj::NbcSetEckenradius(tools::Long nRad
)
502 SetObjectItem(makeSdrEckenradiusItem(nRad
));
505 // #115391# This implementation is based on the object size (aRect) and the
506 // states of IsAutoGrowWidth/Height to correctly set TextMinFrameWidth/Height
507 void SdrTextObj::AdaptTextMinSize()
510 // Only do this for text frame.
513 if (getSdrModelFromSdrObject().IsPasteResize())
514 // Don't do this during paste resize.
517 const bool bW
= IsAutoGrowWidth();
518 const bool bH
= IsAutoGrowHeight();
521 // No auto grow requested. Bail out.
524 SfxItemSetFixed
<SDRATTR_TEXT_MINFRAMEHEIGHT
, SDRATTR_TEXT_AUTOGROWHEIGHT
,
525 SDRATTR_TEXT_MINFRAMEWIDTH
, SDRATTR_TEXT_AUTOGROWWIDTH
> // contains SDRATTR_TEXT_MAXFRAMEWIDTH
526 aSet(*GetObjectItemSet().GetPool());
530 // Set minimum width.
531 const tools::Long nDist
= GetTextLeftDistance() + GetTextRightDistance();
532 const tools::Long nW
= std::max
<tools::Long
>(0, getRectangle().GetWidth() - 1 - nDist
); // text width without margins
534 aSet
.Put(makeSdrTextMinFrameWidthItem(nW
));
536 if(!IsVerticalWriting() && mbDisableAutoWidthOnDragging
)
538 mbDisableAutoWidthOnDragging
= true;
539 aSet
.Put(makeSdrTextAutoGrowWidthItem(false));
545 // Set Minimum height.
546 const tools::Long nDist
= GetTextUpperDistance() + GetTextLowerDistance();
547 const tools::Long nH
= std::max
<tools::Long
>(0, getRectangle().GetHeight() - 1 - nDist
); // text height without margins
549 aSet
.Put(makeSdrTextMinFrameHeightItem(nH
));
551 if(IsVerticalWriting() && mbDisableAutoWidthOnDragging
)
553 mbDisableAutoWidthOnDragging
= false;
554 aSet
.Put(makeSdrTextAutoGrowHeightItem(false));
558 SetObjectItemSet(aSet
);
561 void SdrTextObj::ImpSetContourPolygon( SdrOutliner
& rOutliner
, tools::Rectangle
const & rAnchorRect
, bool bLineWidth
) const
563 basegfx::B2DPolyPolygon
aXorPolyPolygon(TakeXorPoly());
564 std::optional
<basegfx::B2DPolyPolygon
> pContourPolyPolygon
;
565 basegfx::B2DHomMatrix
aMatrix(basegfx::utils::createTranslateB2DHomMatrix(
566 -rAnchorRect
.Left(), -rAnchorRect
.Top()));
568 if(maGeo
.m_nRotationAngle
)
571 aMatrix
.rotate(-toRadians(maGeo
.m_nRotationAngle
));
574 aXorPolyPolygon
.transform(aMatrix
);
578 // Take line width into account.
579 // When doing the hit test, avoid this. (Performance!)
580 pContourPolyPolygon
.emplace();
582 // test if shadow needs to be avoided for TakeContour()
583 const SfxItemSet
& rSet
= GetObjectItemSet();
584 bool bShadowOn
= rSet
.Get(SDRATTR_SHADOW
).GetValue();
587 // Remember TextObject currently set at the DrawOutliner, it WILL be
588 // replaced during calculating the outline since it uses an own paint
589 // and that one uses the DrawOutliner, too.
590 const SdrTextObj
* pLastTextObject
= rOutliner
.GetTextObj();
595 rtl::Reference
<SdrTextObj
> pCopy
= SdrObject::Clone(*this, getSdrModelFromSdrObject());
596 pCopy
->SetMergedItem(makeSdrShadowItem(false));
597 *pContourPolyPolygon
= pCopy
->TakeContour();
601 *pContourPolyPolygon
= TakeContour();
605 // restore remembered text object
606 if(pLastTextObject
!= rOutliner
.GetTextObj())
608 rOutliner
.SetTextObj(pLastTextObject
);
611 pContourPolyPolygon
->transform(aMatrix
);
614 rOutliner
.SetPolygon(aXorPolyPolygon
, pContourPolyPolygon
? &*pContourPolyPolygon
: nullptr);
617 void SdrTextObj::TakeUnrotatedSnapRect(tools::Rectangle
& rRect
) const
619 rRect
= getRectangle();
622 // See also: <unnamed>::getTextAnchorRange in svx/source/sdr/primitive2d/sdrdecompositiontools.cxx
623 void SdrTextObj::AdjustRectToTextDistance(tools::Rectangle
& rAnchorRect
) const
625 const tools::Long nLeftDist
= GetTextLeftDistance();
626 const tools::Long nRightDist
= GetTextRightDistance();
627 const tools::Long nUpperDist
= GetTextUpperDistance();
628 const tools::Long nLowerDist
= GetTextLowerDistance();
629 if (!IsVerticalWriting())
631 rAnchorRect
.AdjustLeft(nLeftDist
);
632 rAnchorRect
.AdjustTop(nUpperDist
);
633 rAnchorRect
.AdjustRight(-nRightDist
);
634 rAnchorRect
.AdjustBottom(-nLowerDist
);
636 else if (IsTopToBottom())
638 rAnchorRect
.AdjustLeft(nLowerDist
);
639 rAnchorRect
.AdjustTop(nLeftDist
);
640 rAnchorRect
.AdjustRight(-nUpperDist
);
641 rAnchorRect
.AdjustBottom(-nRightDist
);
645 rAnchorRect
.AdjustLeft(nUpperDist
);
646 rAnchorRect
.AdjustTop(nRightDist
);
647 rAnchorRect
.AdjustRight(-nLowerDist
);
648 rAnchorRect
.AdjustBottom(-nLeftDist
);
651 // Since sizes may be bigger than the object bounds it is necessary to
652 // justify the rect now.
653 ImpJustifyRect(rAnchorRect
);
656 void SdrTextObj::TakeTextAnchorRect(tools::Rectangle
& rAnchorRect
) const
658 tools::Rectangle
aAnkRect(getRectangle()); // the rectangle in which we anchor
659 bool bFrame
=IsTextFrame();
661 TakeUnrotatedSnapRect(aAnkRect
);
663 Point
aRotateRef(aAnkRect
.TopLeft());
664 AdjustRectToTextDistance(aAnkRect
);
667 // TODO: Optimize this.
668 if (aAnkRect
.GetWidth()<2) aAnkRect
.SetRight(aAnkRect
.Left()+1 ); // minimum size h and v: 2 px
669 if (aAnkRect
.GetHeight()<2) aAnkRect
.SetBottom(aAnkRect
.Top()+1 );
671 if (maGeo
.m_nRotationAngle
) {
672 Point
aTmpPt(aAnkRect
.TopLeft());
673 RotatePoint(aTmpPt
,aRotateRef
,maGeo
.mfSinRotationAngle
,maGeo
.mfCosRotationAngle
);
674 aTmpPt
-=aAnkRect
.TopLeft();
675 aAnkRect
.Move(aTmpPt
.X(),aTmpPt
.Y());
677 rAnchorRect
=aAnkRect
;
680 void SdrTextObj::TakeTextRect( SdrOutliner
& rOutliner
, tools::Rectangle
& rTextRect
, bool bNoEditText
,
681 tools::Rectangle
* pAnchorRect
, bool bLineWidth
) const
683 tools::Rectangle aAnkRect
; // the rectangle in which we anchor
684 TakeTextAnchorRect(aAnkRect
);
685 SdrTextVertAdjust eVAdj
=GetTextVerticalAdjust();
686 SdrTextHorzAdjust eHAdj
=GetTextHorizontalAdjust();
687 SdrTextAniKind eAniKind
=GetTextAniKind();
688 SdrTextAniDirection eAniDirection
=GetTextAniDirection();
690 bool bFitToSize(IsFitToSize());
691 bool bContourFrame
=IsContourTextFrame();
693 bool bFrame
=IsTextFrame();
694 EEControlBits nStat0
=rOutliner
.GetControlWord();
698 rOutliner
.SetControlWord(nStat0
|EEControlBits::AUTOPAGESIZE
);
699 rOutliner
.SetMinAutoPaperSize(aNullSize
);
700 rOutliner
.SetMaxAutoPaperSize(Size(1000000,1000000));
703 if (!bFitToSize
&& !bContourFrame
)
705 tools::Long nAnkWdt
=aAnkRect
.GetWidth();
706 tools::Long nAnkHgt
=aAnkRect
.GetHeight();
709 tools::Long nWdt
=nAnkWdt
;
710 tools::Long nHgt
=nAnkHgt
;
712 bool bInEditMode
= IsInEditMode();
714 if (!bInEditMode
&& (eAniKind
==SdrTextAniKind::Scroll
|| eAniKind
==SdrTextAniKind::Alternate
|| eAniKind
==SdrTextAniKind::Slide
))
716 // unlimited paper size for ticker text
717 if (eAniDirection
==SdrTextAniDirection::Left
|| eAniDirection
==SdrTextAniDirection::Right
) nWdt
=1000000;
718 if (eAniDirection
==SdrTextAniDirection::Up
|| eAniDirection
==SdrTextAniDirection::Down
) nHgt
=1000000;
721 bool bChainedFrame
= IsChainable();
722 // Might be required for overflow check working: do limit height to frame if box is chainable.
723 if (!bChainedFrame
) {
724 // #i119885# Do not limit/force height to geometrical frame (vice versa for vertical writing)
726 if(IsVerticalWriting())
736 rOutliner
.SetMaxAutoPaperSize(Size(nWdt
,nHgt
));
739 // New try with _BLOCK for hor and ver after completely
740 // supporting full width for vertical text.
741 if(SDRTEXTHORZADJUST_BLOCK
== eHAdj
&& !IsVerticalWriting())
743 rOutliner
.SetMinAutoPaperSize(Size(nAnkWdt
, 0));
744 rOutliner
.SetMinColumnWrapHeight(nAnkHgt
);
747 if(SDRTEXTVERTADJUST_BLOCK
== eVAdj
&& IsVerticalWriting())
749 rOutliner
.SetMinAutoPaperSize(Size(0, nAnkHgt
));
750 rOutliner
.SetMinColumnWrapHeight(nAnkWdt
);
754 rOutliner
.SetPaperSize(aNullSize
);
756 ImpSetContourPolygon( rOutliner
, aAnkRect
, bLineWidth
);
758 // put text into the outliner, if available from the edit outliner
759 SdrText
* pText
= getActiveText();
760 OutlinerParaObject
* pOutlinerParaObject
= pText
? pText
->GetOutlinerParaObject() : nullptr;
761 std::optional
<OutlinerParaObject
> pPara
;
762 if (mpEditingOutliner
&& !bNoEditText
)
763 pPara
= mpEditingOutliner
->CreateParaObject();
764 else if (pOutlinerParaObject
)
765 pPara
= *pOutlinerParaObject
;
769 const bool bHitTest(&getSdrModelFromSdrObject().GetHitTestOutliner() == &rOutliner
);
770 const SdrTextObj
* pTestObj
= rOutliner
.GetTextObj();
772 if( !pTestObj
|| !bHitTest
|| pTestObj
!= this ||
773 pTestObj
->GetOutlinerParaObject() != pOutlinerParaObject
)
775 if( bHitTest
) // #i33696# take back fix #i27510#
777 rOutliner
.SetTextObj( this );
778 rOutliner
.SetFixedCellHeight(GetMergedItem(SDRATTR_TEXT_USEFIXEDCELLHEIGHT
).GetValue());
781 rOutliner
.SetUpdateLayout(true);
782 rOutliner
.SetText(*pPara
);
787 rOutliner
.SetTextObj( nullptr );
790 rOutliner
.SetUpdateLayout(true);
791 rOutliner
.SetControlWord(nStat0
);
794 pText
->CheckPortionInfo(rOutliner
);
796 Point
aTextPos(aAnkRect
.TopLeft());
797 Size
aTextSiz(rOutliner
.GetPaperSize()); // GetPaperSize() adds a little tolerance, right?
799 // For draw objects containing text correct hor/ver alignment if text is bigger
800 // than the object itself. Without that correction, the text would always be
801 // formatted to the left edge (or top edge when vertical) of the draw object.
804 if(aAnkRect
.GetWidth() < aTextSiz
.Width() && !IsVerticalWriting())
806 // Horizontal case here. Correct only if eHAdj == SDRTEXTHORZADJUST_BLOCK,
807 // else the alignment is wanted.
808 if(SDRTEXTHORZADJUST_BLOCK
== eHAdj
)
810 eHAdj
= SDRTEXTHORZADJUST_CENTER
;
814 if(aAnkRect
.GetHeight() < aTextSiz
.Height() && IsVerticalWriting())
816 // Vertical case here. Correct only if eHAdj == SDRTEXTVERTADJUST_BLOCK,
817 // else the alignment is wanted.
818 if(SDRTEXTVERTADJUST_BLOCK
== eVAdj
)
820 eVAdj
= SDRTEXTVERTADJUST_CENTER
;
825 if (eHAdj
==SDRTEXTHORZADJUST_CENTER
|| eHAdj
==SDRTEXTHORZADJUST_RIGHT
)
827 tools::Long nFreeWdt
=aAnkRect
.GetWidth()-aTextSiz
.Width();
828 if (eHAdj
==SDRTEXTHORZADJUST_CENTER
)
829 aTextPos
.AdjustX(nFreeWdt
/2 );
830 if (eHAdj
==SDRTEXTHORZADJUST_RIGHT
)
831 aTextPos
.AdjustX(nFreeWdt
);
833 if (eVAdj
==SDRTEXTVERTADJUST_CENTER
|| eVAdj
==SDRTEXTVERTADJUST_BOTTOM
)
835 tools::Long nFreeHgt
=aAnkRect
.GetHeight()-aTextSiz
.Height();
836 if (eVAdj
==SDRTEXTVERTADJUST_CENTER
)
837 aTextPos
.AdjustY(nFreeHgt
/2 );
838 if (eVAdj
==SDRTEXTVERTADJUST_BOTTOM
)
839 aTextPos
.AdjustY(nFreeHgt
);
841 if (maGeo
.m_nRotationAngle
)
842 RotatePoint(aTextPos
,aAnkRect
.TopLeft(),maGeo
.mfSinRotationAngle
,maGeo
.mfCosRotationAngle
);
845 *pAnchorRect
=aAnkRect
;
847 // rTextRect might not be correct in some cases at ContourFrame
848 rTextRect
=tools::Rectangle(aTextPos
,aTextSiz
);
853 bool SdrTextObj::CanCreateEditOutlinerParaObject() const
855 if( HasTextImpl( mpEditingOutliner
) )
857 return mpEditingOutliner
->GetParagraphCount() > 0;
862 std::optional
<OutlinerParaObject
> SdrTextObj::CreateEditOutlinerParaObject() const
864 std::optional
<OutlinerParaObject
> pPara
;
865 if( HasTextImpl( mpEditingOutliner
) )
867 sal_Int32 nParaCount
= mpEditingOutliner
->GetParagraphCount();
868 pPara
= mpEditingOutliner
->CreateParaObject(0, nParaCount
);
873 void SdrTextObj::ImpSetCharStretching(SdrOutliner
& rOutliner
, const Size
& rTextSize
, const Size
& rShapeSize
, Fraction
& rFitXCorrection
)
875 OutputDevice
* pOut
= rOutliner
.GetRefDevice();
876 bool bNoStretching(false);
878 if(pOut
&& pOut
->GetOutDevType() == OUTDEV_PRINTER
)
880 // check whether CharStretching is possible at all
881 GDIMetaFile
* pMtf
= pOut
->GetConnectMetaFile();
882 OUString
aTestString(u
'J');
884 if(pMtf
&& (!pMtf
->IsRecord() || pMtf
->IsPause()))
890 vcl::Font
aOriginalFont(pOut
->GetFont());
891 vcl::Font
aTmpFont( OutputDevice::GetDefaultFont( DefaultFontType::SERIF
, LANGUAGE_SYSTEM
, GetDefaultFontFlags::OnlyOne
) );
893 aTmpFont
.SetFontSize(Size(0,100));
894 pOut
->SetFont(aTmpFont
);
895 Size
aSize1(pOut
->GetTextWidth(aTestString
), pOut
->GetTextHeight());
896 aTmpFont
.SetFontSize(Size(800,100));
897 pOut
->SetFont(aTmpFont
);
898 Size
aSize2(pOut
->GetTextWidth(aTestString
), pOut
->GetTextHeight());
899 pOut
->SetFont(aOriginalFont
);
904 bNoStretching
= (aSize1
== aSize2
);
907 // Windows zooms the font proportionally when using Size(100,500),
908 // we don't like that.
909 if(aSize2
.Height() >= aSize1
.Height() * 2)
911 bNoStretching
= true;
916 rOutliner
.setRoundFontSizeToPt(false);
918 unsigned nLoopCount
=0;
919 bool bNoMoreLoop
= false;
920 tools::Long nXDiff0
=0x7FFFFFFF;
921 tools::Long nWantWdt
=rShapeSize
.Width();
922 tools::Long nIsWdt
=rTextSize
.Width();
923 if (nIsWdt
==0) nIsWdt
=1;
925 tools::Long nWantHgt
=rShapeSize
.Height();
926 tools::Long nIsHgt
=rTextSize
.Height();
927 if (nIsHgt
==0) nIsHgt
=1;
929 tools::Long nXTolPl
=nWantWdt
/100; // tolerance: +1%
930 tools::Long nXTolMi
=nWantWdt
/25; // tolerance: -4%
931 tools::Long nXCorr
=nWantWdt
/20; // correction scale: 5%
933 double nX
= (nWantWdt
* 100.0) / double(nIsWdt
); // calculate X stretching
934 double nY
= (nWantHgt
* 100.0) / double(nIsHgt
); // calculate Y stretching
937 { // might only be possible proportionally
949 while (nLoopCount
<5 && !bNoMoreLoop
)
979 // exception, there is no text yet (horizontal case)
986 // exception, there is no text yet (vertical case)
992 rOutliner
.setScalingParameters({nX
, nY
});
994 Size
aSiz(rOutliner
.CalcTextSize());
995 tools::Long nXDiff
= aSiz
.Width() - nWantWdt
;
996 rFitXCorrection
=Fraction(nWantWdt
,aSiz
.Width());
997 if (((nXDiff
>=nXTolMi
|| !bChkX
) && nXDiff
<=nXTolPl
) || nXDiff
==nXDiff0
) {
1000 // correct stretching factors
1001 tools::Long nMul
= nWantWdt
;
1002 tools::Long nDiv
= aSiz
.Width();
1003 if (std::abs(nXDiff
) <= 2 * nXCorr
)
1006 nDiv
+= (nMul
- nDiv
) / 2.0; // but only add half of what we calculated,
1008 nMul
+= (nDiv
- nMul
) / 2.0;// because the EditEngine calculates wrongly later on
1010 nX
= nX
* double(nMul
) / double(nDiv
);
1018 OUString
SdrTextObj::TakeObjNameSingul() const
1024 case SdrObjKind::OutlineText
:
1026 aStr
= SvxResId(STR_ObjNameSingulOUTLINETEXT
);
1030 case SdrObjKind::TitleText
:
1032 aStr
= SvxResId(STR_ObjNameSingulTITLETEXT
);
1039 aStr
= SvxResId(STR_ObjNameSingulTEXTLNK
);
1041 aStr
= SvxResId(STR_ObjNameSingulTEXT
);
1046 OutlinerParaObject
* pOutlinerParaObject
= GetOutlinerParaObject();
1047 if(pOutlinerParaObject
&& meTextKind
!= SdrObjKind::OutlineText
)
1049 // shouldn't currently cause any problems at OUTLINETEXT
1050 OUString
aStr2(comphelper::string::stripStart(pOutlinerParaObject
->GetTextObject().GetText(0), ' '));
1052 // avoid non expanded text portions in object name
1053 // (second condition is new)
1054 if(!aStr2
.isEmpty() && aStr2
.indexOf(u
'\x00FF') == -1)
1056 // space between ResStr and content text
1059 if(aStr2
.getLength() > 10)
1061 aStr2
= OUString::Concat(aStr2
.subView(0, 8)) + "...";
1064 aStr
+= aStr2
+ "\'";
1068 OUString
sName(aStr
);
1070 OUString
aName(GetName());
1071 if (!aName
.isEmpty())
1072 sName
+= " '" + aName
+ "'";
1077 OUString
SdrTextObj::TakeObjNamePlural() const
1082 case SdrObjKind::OutlineText
: sName
=SvxResId(STR_ObjNamePluralOUTLINETEXT
); break;
1083 case SdrObjKind::TitleText
: sName
=SvxResId(STR_ObjNamePluralTITLETEXT
); break;
1085 if (IsLinkedText()) {
1086 sName
=SvxResId(STR_ObjNamePluralTEXTLNK
);
1088 sName
=SvxResId(STR_ObjNamePluralTEXT
);
1095 rtl::Reference
<SdrObject
> SdrTextObj::CloneSdrObject(SdrModel
& rTargetModel
) const
1097 return new SdrTextObj(rTargetModel
, *this);
1100 basegfx::B2DPolyPolygon
SdrTextObj::TakeXorPoly() const
1102 tools::Polygon
aPol(getRectangle());
1103 if (maGeo
.m_nShearAngle
)
1104 ShearPoly(aPol
, getRectangle().TopLeft(), maGeo
.mfTanShearAngle
);
1105 if (maGeo
.m_nRotationAngle
)
1106 RotatePoly(aPol
, getRectangle().TopLeft(), maGeo
.mfSinRotationAngle
, maGeo
.mfCosRotationAngle
);
1108 basegfx::B2DPolyPolygon aRetval
;
1109 aRetval
.append(aPol
.getB2DPolygon());
1113 basegfx::B2DPolyPolygon
SdrTextObj::TakeContour() const
1115 basegfx::B2DPolyPolygon
aRetval(SdrAttrObj::TakeContour());
1117 // and now add the BoundRect of the text, if necessary
1118 if ( GetOutlinerParaObject() && !IsFontwork() && !IsContourTextFrame() )
1120 // using Clone()-Paint() strategy inside TakeContour() leaves a destroyed
1121 // SdrObject as pointer in DrawOutliner. Set *this again in fetching the outliner
1123 SdrOutliner
& rOutliner
=ImpGetDrawOutliner();
1125 tools::Rectangle aAnchor2
;
1126 tools::Rectangle aR
;
1127 TakeTextRect(rOutliner
,aR
,false,&aAnchor2
);
1129 bool bFitToSize(IsFitToSize());
1130 if (bFitToSize
) aR
=aAnchor2
;
1131 tools::Polygon
aPol(aR
);
1132 if (maGeo
.m_nRotationAngle
) RotatePoly(aPol
,aR
.TopLeft(), maGeo
.mfSinRotationAngle
, maGeo
.mfCosRotationAngle
);
1134 aRetval
.append(aPol
.getB2DPolygon());
1140 void SdrTextObj::RecalcSnapRect()
1142 if (maGeo
.m_nRotationAngle
|| maGeo
.m_nShearAngle
)
1144 maSnapRect
= Rect2Poly(getRectangle(), maGeo
).GetBoundRect();
1146 maSnapRect
= getRectangle();
1150 sal_uInt32
SdrTextObj::GetSnapPointCount() const
1155 Point
SdrTextObj::GetSnapPoint(sal_uInt32 i
) const
1158 auto aRectangle
= getRectangle();
1160 case 0: aP
= aRectangle
.TopLeft(); break;
1161 case 1: aP
= aRectangle
.TopRight(); break;
1162 case 2: aP
= aRectangle
.BottomLeft(); break;
1163 case 3: aP
= aRectangle
.BottomRight(); break;
1164 default: aP
= aRectangle
.Center(); break;
1166 if (maGeo
.m_nShearAngle
)
1167 ShearPoint(aP
, aRectangle
.TopLeft(), maGeo
.mfTanShearAngle
);
1168 if (maGeo
.m_nRotationAngle
)
1169 RotatePoint(aP
, aRectangle
.TopLeft(), maGeo
.mfSinRotationAngle
, maGeo
.mfCosRotationAngle
);
1173 // Extracted from ImpGetDrawOutliner()
1174 void SdrTextObj::ImpInitDrawOutliner( SdrOutliner
& rOutl
) const
1176 rOutl
.SetUpdateLayout(false);
1177 OutlinerMode nOutlinerMode
= OutlinerMode::OutlineObject
;
1178 if ( !IsOutlText() )
1179 nOutlinerMode
= OutlinerMode::TextObject
;
1180 rOutl
.Init( nOutlinerMode
);
1182 rOutl
.resetScalingParameters();
1184 EEControlBits nStat
=rOutl
.GetControlWord();
1185 nStat
&= ~EEControlBits(EEControlBits::STRETCHING
|EEControlBits::AUTOPAGESIZE
);
1186 rOutl
.SetControlWord(nStat
);
1187 Size
aMaxSize(100000,100000);
1188 rOutl
.SetMinAutoPaperSize(Size());
1189 rOutl
.SetMaxAutoPaperSize(aMaxSize
);
1190 rOutl
.SetPaperSize(aMaxSize
);
1191 rOutl
.ClearPolygon();
1194 SdrOutliner
& SdrTextObj::ImpGetDrawOutliner() const
1196 SdrOutliner
& rOutl(getSdrModelFromSdrObject().GetDrawOutliner(this));
1198 // Code extracted to ImpInitDrawOutliner()
1199 ImpInitDrawOutliner( rOutl
);
1204 // Extracted from Paint()
1205 void SdrTextObj::ImpSetupDrawOutlinerForPaint( bool bContourFrame
,
1206 SdrOutliner
& rOutliner
,
1207 tools::Rectangle
& rTextRect
,
1208 tools::Rectangle
& rAnchorRect
,
1209 tools::Rectangle
& rPaintRect
,
1210 Fraction
& rFitXCorrection
) const
1214 // FitToSize can't be used together with ContourFrame for now
1215 if (IsFitToSize() || IsAutoFit())
1217 EEControlBits nStat
=rOutliner
.GetControlWord();
1218 nStat
|=EEControlBits::STRETCHING
|EEControlBits::AUTOPAGESIZE
;
1219 rOutliner
.SetControlWord(nStat
);
1222 rOutliner
.SetFixedCellHeight(GetMergedItem(SDRATTR_TEXT_USEFIXEDCELLHEIGHT
).GetValue());
1223 TakeTextRect(rOutliner
, rTextRect
, false, &rAnchorRect
);
1224 rPaintRect
= rTextRect
;
1229 // FitToSize can't be used together with ContourFrame for now
1232 ImpSetCharStretching(rOutliner
,rTextRect
.GetSize(),rAnchorRect
.GetSize(),rFitXCorrection
);
1233 rPaintRect
=rAnchorRect
;
1235 else if (IsAutoFit())
1237 setupAutoFitText(rOutliner
);
1241 double SdrTextObj::GetFontScale() const
1243 SdrOutliner
& rOutliner
= ImpGetDrawOutliner();
1244 // This eventually calls setupAutoFitText
1245 UpdateOutlinerFormatting(rOutliner
, o3tl::temporary(tools::Rectangle()));
1247 return rOutliner
.getScalingParameters().fFontY
;
1250 double SdrTextObj::GetSpacingScale() const
1252 SdrOutliner
& rOutliner
= ImpGetDrawOutliner();
1253 // This eventually calls setupAutoFitText
1254 UpdateOutlinerFormatting(rOutliner
, o3tl::temporary(tools::Rectangle()));
1256 return rOutliner
.getScalingParameters().fSpacingY
;
1259 void SdrTextObj::setupAutoFitText(SdrOutliner
& rOutliner
) const
1261 const Size aShapeSize
= GetSnapRect().GetSize();
1262 Size
aSize(aShapeSize
.Width() - GetTextLeftDistance() - GetTextRightDistance(),
1263 aShapeSize
.Height() - GetTextUpperDistance() - GetTextLowerDistance());
1265 setupAutoFitText(rOutliner
, aSize
);
1267 void SdrTextObj::setupAutoFitText(SdrOutliner
& rOutliner
, const Size
& rTextBoxSize
) const
1269 rOutliner
.setRoundFontSizeToPt(true); // We need to round the font size nearest integer pt size
1270 rOutliner
.SetMaxAutoPaperSize(rTextBoxSize
);
1271 rOutliner
.SetPaperSize(rTextBoxSize
);
1273 const SdrTextFitToSizeTypeItem
& rItem
= GetObjectItem(SDRATTR_TEXT_FITTOSIZE
);
1275 double fFontScale
= rItem
.getFontScale();
1276 double fSpacingScale
= rItem
.getSpacingScale();
1278 if (fFontScale
> 0.0 && fSpacingScale
> 0.0 && !mbInEditMode
)
1280 rOutliner
.setScalingParameters({ fFontScale
, fFontScale
, 100.0, fSpacingScale
});
1284 rOutliner
.resetScalingParameters();
1287 rOutliner
.QuickFormatDoc();
1290 void SdrTextObj::SetupOutlinerFormatting( SdrOutliner
& rOutl
, tools::Rectangle
& rPaintRect
) const
1292 ImpInitDrawOutliner( rOutl
);
1293 UpdateOutlinerFormatting( rOutl
, rPaintRect
);
1296 void SdrTextObj::UpdateOutlinerFormatting( SdrOutliner
& rOutl
, tools::Rectangle
& rPaintRect
) const
1298 tools::Rectangle aTextRect
;
1299 tools::Rectangle aAnchorRect
;
1300 Fraction
aFitXCorrection(1,1);
1302 const bool bContourFrame(IsContourTextFrame());
1303 const MapMode
aMapMode(getSdrModelFromSdrObject().GetScaleUnit());
1305 rOutl
.SetRefMapMode(aMapMode
);
1306 ImpSetupDrawOutlinerForPaint(
1316 OutlinerParaObject
* SdrTextObj::GetOutlinerParaObject() const
1318 SdrText
* pText
= getActiveText();
1320 return pText
->GetOutlinerParaObject();
1325 void SdrTextObj::NbcSetOutlinerParaObject(std::optional
<OutlinerParaObject
> pTextObject
)
1327 NbcSetOutlinerParaObjectForText( std::move(pTextObject
), getActiveText() );
1332 bool IsAutoGrow(const SdrTextObj
& rObj
)
1334 bool bAutoGrow
= rObj
.IsAutoGrowHeight() || rObj
.IsAutoGrowWidth();
1335 return bAutoGrow
&& !utl::ConfigManager::IsFuzzing();
1339 void SdrTextObj::NbcSetOutlinerParaObjectForText( std::optional
<OutlinerParaObject
> pTextObject
, SdrText
* pText
)
1342 pText
->SetOutlinerParaObject( std::move(pTextObject
) );
1344 if (pText
&& pText
->GetOutlinerParaObject())
1346 SvxWritingModeItem
aWritingMode(pText
->GetOutlinerParaObject()->IsEffectivelyVertical() && pText
->GetOutlinerParaObject()->IsTopToBottom()
1347 ? css::text::WritingMode_TB_RL
1348 : css::text::WritingMode_LR_TB
,
1349 SDRATTR_TEXTDIRECTION
);
1350 GetProperties().SetObjectItemDirect(aWritingMode
);
1354 if (IsTextFrame() && IsAutoGrow(*this))
1355 { // adapt text frame!
1356 NbcAdjustTextFrameWidthAndHeight();
1360 // the SnapRect keeps its size
1361 SetBoundAndSnapRectsDirty(true);
1364 // always invalidate BoundRect on change
1365 SetBoundRectDirty();
1368 ImpSetTextStyleSheetListeners();
1371 void SdrTextObj::NbcReformatText()
1373 SdrText
* pText
= getActiveText();
1374 if( !(pText
&& pText
->GetOutlinerParaObject()) )
1377 pText
->ReformatText();
1380 NbcAdjustTextFrameWidthAndHeight();
1384 // the SnapRect keeps its size
1385 SetBoundRectDirty();
1386 SetBoundAndSnapRectsDirty(/*bNotMyself*/true);
1391 // Necessary here since we have no compare operator at the outliner
1392 // para object which may detect changes regarding the combination
1393 // of outliner para data and configuration (e.g., change of
1394 // formatting of text numerals)
1395 GetViewContact().flushViewObjectContacts(false);
1398 std::unique_ptr
<SdrObjGeoData
> SdrTextObj::NewGeoData() const
1400 return std::make_unique
<SdrTextObjGeoData
>();
1403 void SdrTextObj::SaveGeoData(SdrObjGeoData
& rGeo
) const
1405 SdrAttrObj::SaveGeoData(rGeo
);
1406 SdrTextObjGeoData
& rTGeo
=static_cast<SdrTextObjGeoData
&>(rGeo
);
1407 rTGeo
.maRect
= getRectangle();
1408 rTGeo
.maGeo
= maGeo
;
1411 void SdrTextObj::RestoreGeoData(const SdrObjGeoData
& rGeo
)
1412 { // RectsDirty is called by SdrObject
1413 SdrAttrObj::RestoreGeoData(rGeo
);
1414 const SdrTextObjGeoData
& rTGeo
=static_cast<const SdrTextObjGeoData
&>(rGeo
);
1415 NbcSetLogicRect(rTGeo
.maRect
);
1416 maGeo
= rTGeo
.maGeo
;
1420 drawing::TextFitToSizeType
SdrTextObj::GetFitToSize() const
1422 drawing::TextFitToSizeType eType
= drawing::TextFitToSizeType_NONE
;
1424 if(!IsAutoGrowWidth())
1425 eType
= GetObjectItem(SDRATTR_TEXT_FITTOSIZE
).GetValue();
1430 const tools::Rectangle
& SdrTextObj::GetGeoRect() const
1432 return getRectangle();
1435 void SdrTextObj::ForceOutlinerParaObject()
1437 SdrText
* pText
= getActiveText();
1438 if( pText
&& (pText
->GetOutlinerParaObject() == nullptr) )
1440 OutlinerMode nOutlMode
= OutlinerMode::TextObject
;
1441 if( IsTextFrame() && meTextKind
== SdrObjKind::OutlineText
)
1442 nOutlMode
= OutlinerMode::OutlineObject
;
1444 pText
->ForceOutlinerParaObject( nOutlMode
);
1448 TextChain
*SdrTextObj::GetTextChain() const
1450 //if (!IsChainable())
1453 return getSdrModelFromSdrObject().GetTextChain();
1456 bool SdrTextObj::IsVerticalWriting() const
1458 if(mpEditingOutliner
)
1460 return mpEditingOutliner
->IsVertical();
1463 OutlinerParaObject
* pOutlinerParaObject
= GetOutlinerParaObject();
1464 if(pOutlinerParaObject
)
1466 return pOutlinerParaObject
->IsEffectivelyVertical();
1472 void SdrTextObj::SetVerticalWriting(bool bVertical
)
1474 OutlinerParaObject
* pOutlinerParaObject
= GetOutlinerParaObject();
1476 if( !pOutlinerParaObject
&& bVertical
)
1478 // we only need to force an outliner para object if the default of
1479 // horizontal text is changed
1480 ForceOutlinerParaObject();
1481 pOutlinerParaObject
= GetOutlinerParaObject();
1484 if (!pOutlinerParaObject
||
1485 (pOutlinerParaObject
->IsEffectivelyVertical() == bVertical
))
1488 // get item settings
1489 const SfxItemSet
& rSet
= GetObjectItemSet();
1490 bool bAutoGrowWidth
= rSet
.Get(SDRATTR_TEXT_AUTOGROWWIDTH
).GetValue();
1491 bool bAutoGrowHeight
= rSet
.Get(SDRATTR_TEXT_AUTOGROWHEIGHT
).GetValue();
1493 // Also exchange hor/ver adjust items
1494 SdrTextHorzAdjust eHorz
= rSet
.Get(SDRATTR_TEXT_HORZADJUST
).GetValue();
1495 SdrTextVertAdjust eVert
= rSet
.Get(SDRATTR_TEXT_VERTADJUST
).GetValue();
1497 // rescue object size
1498 tools::Rectangle aObjectRect
= GetSnapRect();
1500 // prepare ItemSet to set exchanged width and height items
1501 SfxItemSetFixed
<SDRATTR_TEXT_AUTOGROWHEIGHT
, SDRATTR_TEXT_AUTOGROWHEIGHT
,
1502 // Expanded item ranges to also support hor and ver adjust.
1503 SDRATTR_TEXT_VERTADJUST
, SDRATTR_TEXT_VERTADJUST
,
1504 SDRATTR_TEXT_AUTOGROWWIDTH
, SDRATTR_TEXT_HORZADJUST
> aNewSet(*rSet
.GetPool());
1507 aNewSet
.Put(makeSdrTextAutoGrowWidthItem(bAutoGrowHeight
));
1508 aNewSet
.Put(makeSdrTextAutoGrowHeightItem(bAutoGrowWidth
));
1510 // Exchange horz and vert adjusts
1513 case SDRTEXTVERTADJUST_TOP
: aNewSet
.Put(SdrTextHorzAdjustItem(SDRTEXTHORZADJUST_RIGHT
)); break;
1514 case SDRTEXTVERTADJUST_CENTER
: aNewSet
.Put(SdrTextHorzAdjustItem(SDRTEXTHORZADJUST_CENTER
)); break;
1515 case SDRTEXTVERTADJUST_BOTTOM
: aNewSet
.Put(SdrTextHorzAdjustItem(SDRTEXTHORZADJUST_LEFT
)); break;
1516 case SDRTEXTVERTADJUST_BLOCK
: aNewSet
.Put(SdrTextHorzAdjustItem(SDRTEXTHORZADJUST_BLOCK
)); break;
1520 case SDRTEXTHORZADJUST_LEFT
: aNewSet
.Put(SdrTextVertAdjustItem(SDRTEXTVERTADJUST_BOTTOM
)); break;
1521 case SDRTEXTHORZADJUST_CENTER
: aNewSet
.Put(SdrTextVertAdjustItem(SDRTEXTVERTADJUST_CENTER
)); break;
1522 case SDRTEXTHORZADJUST_RIGHT
: aNewSet
.Put(SdrTextVertAdjustItem(SDRTEXTVERTADJUST_TOP
)); break;
1523 case SDRTEXTHORZADJUST_BLOCK
: aNewSet
.Put(SdrTextVertAdjustItem(SDRTEXTVERTADJUST_BLOCK
)); break;
1526 SetObjectItemSet(aNewSet
);
1528 pOutlinerParaObject
= GetOutlinerParaObject();
1529 if (pOutlinerParaObject
)
1531 // set ParaObject orientation accordingly
1532 pOutlinerParaObject
->SetVertical(bVertical
);
1535 // restore object size
1536 SetSnapRect(aObjectRect
);
1539 bool SdrTextObj::IsTopToBottom() const
1541 if (mpEditingOutliner
)
1542 return mpEditingOutliner
->IsTopToBottom();
1544 if (OutlinerParaObject
* pOutlinerParaObject
= GetOutlinerParaObject())
1545 return pOutlinerParaObject
->IsTopToBottom();
1550 // transformation interface for StarOfficeAPI. This implements support for
1551 // homogeneous 3x3 matrices containing the transformation of the SdrObject. At the
1552 // moment it contains a shearX, rotation and translation, but for setting all linear
1553 // transforms like Scale, ShearX, ShearY, Rotate and Translate are supported.
1556 // gets base transformation and rectangle of object. If it's an SdrPathObj it fills the PolyPolygon
1557 // with the base geometry and returns TRUE. Otherwise it returns FALSE.
1558 bool SdrTextObj::TRGetBaseGeometry(basegfx::B2DHomMatrix
& rMatrix
, basegfx::B2DPolyPolygon
& /*rPolyPolygon*/) const
1560 // get turn and shear
1561 double fRotate
= toRadians(maGeo
.m_nRotationAngle
);
1562 double fShearX
= toRadians(maGeo
.m_nShearAngle
);
1564 // get aRect, this is the unrotated snaprect
1565 tools::Rectangle
aRectangle(getRectangle());
1567 // fill other values
1568 basegfx::B2DTuple
aScale(aRectangle
.GetWidth(), aRectangle
.GetHeight());
1569 basegfx::B2DTuple
aTranslate(aRectangle
.Left(), aRectangle
.Top());
1571 // position maybe relative to anchorpos, convert
1572 if( getSdrModelFromSdrObject().IsWriter() )
1574 if(GetAnchorPos().X() || GetAnchorPos().Y())
1576 aTranslate
-= basegfx::B2DTuple(GetAnchorPos().X(), GetAnchorPos().Y());
1581 rMatrix
= basegfx::utils::createScaleShearXRotateTranslateB2DHomMatrix(
1583 basegfx::fTools::equalZero(fShearX
) ? 0.0 : tan(fShearX
),
1584 basegfx::fTools::equalZero(fRotate
) ? 0.0 : -fRotate
,
1590 // sets the base geometry of the object using infos contained in the homogeneous 3x3 matrix.
1591 // If it's an SdrPathObj it will use the provided geometry information. The Polygon has
1592 // to use (0,0) as upper left and will be scaled to the given size in the matrix.
1593 void SdrTextObj::TRSetBaseGeometry(const basegfx::B2DHomMatrix
& rMatrix
, const basegfx::B2DPolyPolygon
& /*rPolyPolygon*/)
1596 basegfx::B2DTuple aScale
;
1597 basegfx::B2DTuple aTranslate
;
1598 double fRotate(0.0);
1599 double fShearX(0.0);
1600 rMatrix
.decompose(aScale
, aTranslate
, fRotate
, fShearX
);
1603 bool bFlipX
= aScale
.getX() < 0.0,
1604 bFlipY
= aScale
.getY() < 0.0;
1607 aScale
.setX(fabs(aScale
.getX()));
1611 aScale
.setY(fabs(aScale
.getY()));
1614 // reset object shear and rotations
1615 maGeo
.m_nRotationAngle
= 0_deg100
;
1616 maGeo
.RecalcSinCos();
1617 maGeo
.m_nShearAngle
= 0_deg100
;
1620 // if anchor is used, make position relative to it
1621 if( getSdrModelFromSdrObject().IsWriter() )
1623 if(GetAnchorPos().X() || GetAnchorPos().Y())
1625 aTranslate
+= basegfx::B2DTuple(GetAnchorPos().X(), GetAnchorPos().Y());
1629 // build and set BaseRect (use scale)
1630 Size
aSize(FRound(aScale
.getX()), FRound(aScale
.getY()));
1631 tools::Rectangle
aBaseRect(Point(), aSize
);
1632 SetSnapRect(aBaseRect
);
1637 Mirror(Point(), Point(0, 1));
1641 Mirror(Point(), Point(1, 0));
1645 if(!basegfx::fTools::equalZero(fShearX
))
1648 aGeoStat
.m_nShearAngle
= Degree100(FRound(basegfx::rad2deg
<100>(atan(fShearX
))));
1649 aGeoStat
.RecalcTan();
1650 Shear(Point(), aGeoStat
.m_nShearAngle
, aGeoStat
.mfTanShearAngle
, false);
1654 if(!basegfx::fTools::equalZero(fRotate
))
1659 // fRotate is matematically correct, but aGeoStat.nRotationAngle is
1660 // mirrored -> mirror value here
1661 aGeoStat
.m_nRotationAngle
= NormAngle36000(Degree100(FRound(-basegfx::rad2deg
<100>(fRotate
))));
1662 aGeoStat
.RecalcSinCos();
1663 Rotate(Point(), aGeoStat
.m_nRotationAngle
, aGeoStat
.mfSinRotationAngle
, aGeoStat
.mfCosRotationAngle
);
1667 if(!aTranslate
.equalZero())
1669 Move(Size(FRound(aTranslate
.getX()), FRound(aTranslate
.getY())));
1673 bool SdrTextObj::IsReallyEdited() const
1675 return mpEditingOutliner
&& mpEditingOutliner
->IsModified();
1678 // moved inlines here form hxx
1680 tools::Long
SdrTextObj::GetEckenradius() const
1682 return GetObjectItemSet().Get(SDRATTR_CORNER_RADIUS
).GetValue();
1685 tools::Long
SdrTextObj::GetMinTextFrameHeight() const
1687 return GetObjectItemSet().Get(SDRATTR_TEXT_MINFRAMEHEIGHT
).GetValue();
1690 tools::Long
SdrTextObj::GetMaxTextFrameHeight() const
1692 return GetObjectItemSet().Get(SDRATTR_TEXT_MAXFRAMEHEIGHT
).GetValue();
1695 tools::Long
SdrTextObj::GetMinTextFrameWidth() const
1697 return GetObjectItemSet().Get(SDRATTR_TEXT_MINFRAMEWIDTH
).GetValue();
1700 tools::Long
SdrTextObj::GetMaxTextFrameWidth() const
1702 return GetObjectItemSet().Get(SDRATTR_TEXT_MAXFRAMEWIDTH
).GetValue();
1705 bool SdrTextObj::IsFontwork() const
1707 return !mbTextFrame
// Default is FALSE
1708 && GetObjectItemSet().Get(XATTR_FORMTXTSTYLE
).GetValue() != XFormTextStyle::NONE
;
1711 bool SdrTextObj::IsHideContour() const
1713 return !mbTextFrame
// Default is: no, don't HideContour; HideContour not together with TextFrames
1714 && GetObjectItemSet().Get(XATTR_FORMTXTHIDEFORM
).GetValue();
1717 bool SdrTextObj::IsContourTextFrame() const
1719 return !mbTextFrame
// ContourFrame not together with normal TextFrames
1720 && GetObjectItemSet().Get(SDRATTR_TEXT_CONTOURFRAME
).GetValue();
1723 tools::Long
SdrTextObj::GetTextLeftDistance() const
1725 return GetObjectItemSet().Get(SDRATTR_TEXT_LEFTDIST
).GetValue();
1728 tools::Long
SdrTextObj::GetTextRightDistance() const
1730 return GetObjectItemSet().Get(SDRATTR_TEXT_RIGHTDIST
).GetValue();
1733 tools::Long
SdrTextObj::GetTextUpperDistance() const
1735 return GetObjectItemSet().Get(SDRATTR_TEXT_UPPERDIST
).GetValue();
1738 tools::Long
SdrTextObj::GetTextLowerDistance() const
1740 return GetObjectItemSet().Get(SDRATTR_TEXT_LOWERDIST
).GetValue();
1743 SdrTextAniKind
SdrTextObj::GetTextAniKind() const
1745 return GetObjectItemSet().Get(SDRATTR_TEXT_ANIKIND
).GetValue();
1748 SdrTextAniDirection
SdrTextObj::GetTextAniDirection() const
1750 return GetObjectItemSet().Get(SDRATTR_TEXT_ANIDIRECTION
).GetValue();
1753 bool SdrTextObj::HasTextColumnsNumber() const
1755 return GetObjectItemSet().HasItem(SDRATTR_TEXTCOLUMNS_NUMBER
);
1758 sal_Int16
SdrTextObj::GetTextColumnsNumber() const
1760 return GetObjectItemSet().Get(SDRATTR_TEXTCOLUMNS_NUMBER
).GetValue();
1763 void SdrTextObj::SetTextColumnsNumber(sal_Int16 nColumns
)
1765 SetObjectItem(SfxInt16Item(SDRATTR_TEXTCOLUMNS_NUMBER
, nColumns
));
1768 bool SdrTextObj::HasTextColumnsSpacing() const
1770 return GetObjectItemSet().HasItem(SDRATTR_TEXTCOLUMNS_SPACING
);
1773 sal_Int32
SdrTextObj::GetTextColumnsSpacing() const
1775 return GetObjectItemSet().Get(SDRATTR_TEXTCOLUMNS_SPACING
).GetValue();
1778 void SdrTextObj::SetTextColumnsSpacing(sal_Int32 nSpacing
)
1780 SetObjectItem(SdrMetricItem(SDRATTR_TEXTCOLUMNS_SPACING
, nSpacing
));
1783 // Get necessary data for text scroll animation. ATM base it on a Text-Metafile and a
1784 // painting rectangle. Rotation is excluded from the returned values.
1785 GDIMetaFile
* SdrTextObj::GetTextScrollMetaFileAndRectangle(
1786 tools::Rectangle
& rScrollRectangle
, tools::Rectangle
& rPaintRectangle
)
1788 GDIMetaFile
* pRetval
= nullptr;
1789 SdrOutliner
& rOutliner
= ImpGetDrawOutliner();
1790 tools::Rectangle aTextRect
;
1791 tools::Rectangle aAnchorRect
;
1792 tools::Rectangle aPaintRect
;
1793 Fraction
aFitXCorrection(1,1);
1794 bool bContourFrame(IsContourTextFrame());
1796 // get outliner set up. To avoid getting a somehow rotated MetaFile,
1797 // temporarily disable object rotation.
1798 Degree100
nAngle(maGeo
.m_nRotationAngle
);
1799 maGeo
.m_nRotationAngle
= 0_deg100
;
1800 ImpSetupDrawOutlinerForPaint( bContourFrame
, rOutliner
, aTextRect
, aAnchorRect
, aPaintRect
, aFitXCorrection
);
1801 maGeo
.m_nRotationAngle
= nAngle
;
1803 tools::Rectangle
aScrollFrameRect(aPaintRect
);
1804 const SfxItemSet
& rSet
= GetObjectItemSet();
1805 SdrTextAniDirection eDirection
= rSet
.Get(SDRATTR_TEXT_ANIDIRECTION
).GetValue();
1807 if(SdrTextAniDirection::Left
== eDirection
|| SdrTextAniDirection::Right
== eDirection
)
1809 aScrollFrameRect
.SetLeft( aAnchorRect
.Left() );
1810 aScrollFrameRect
.SetRight( aAnchorRect
.Right() );
1813 if(SdrTextAniDirection::Up
== eDirection
|| SdrTextAniDirection::Down
== eDirection
)
1815 aScrollFrameRect
.SetTop( aAnchorRect
.Top() );
1816 aScrollFrameRect
.SetBottom( aAnchorRect
.Bottom() );
1819 // create the MetaFile
1820 pRetval
= new GDIMetaFile
;
1821 ScopedVclPtrInstance
< VirtualDevice
> pBlackHole
;
1822 pBlackHole
->EnableOutput(false);
1823 pRetval
->Record(pBlackHole
);
1824 Point aPaintPos
= aPaintRect
.TopLeft();
1826 rOutliner
.Draw(*pBlackHole
, aPaintPos
);
1829 pRetval
->WindStart();
1831 // return PaintRectanglePixel and pRetval;
1832 rScrollRectangle
= aScrollFrameRect
;
1833 rPaintRectangle
= aPaintRect
;
1838 // Access to TextAnimationAllowed flag
1839 bool SdrTextObj::IsAutoFit() const
1841 return GetFitToSize() == drawing::TextFitToSizeType_AUTOFIT
;
1844 bool SdrTextObj::IsFitToSize() const
1846 const drawing::TextFitToSizeType eFit
= GetFitToSize();
1847 return (eFit
== drawing::TextFitToSizeType_PROPORTIONAL
1848 || eFit
== drawing::TextFitToSizeType_ALLLINES
);
1851 void SdrTextObj::SetTextAnimationAllowed(bool bNew
)
1853 if(mbTextAnimationAllowed
!= bNew
)
1855 mbTextAnimationAllowed
= bNew
;
1860 /** called from the SdrObjEditView during text edit when the status of the edit outliner changes */
1861 void SdrTextObj::onEditOutlinerStatusEvent( EditStatus
* pEditStatus
)
1863 const EditStatusFlags nStat
= pEditStatus
->GetStatusWord();
1864 const bool bGrowX
= bool(nStat
& EditStatusFlags::TEXTWIDTHCHANGED
);
1865 const bool bGrowY
= bool(nStat
& EditStatusFlags::TextHeightChanged
);
1866 if(!(mbTextFrame
&& (bGrowX
|| bGrowY
)))
1869 if ((bGrowX
&& IsAutoGrowWidth()) || (bGrowY
&& IsAutoGrowHeight()))
1871 AdjustTextFrameWidthAndHeight();
1873 else if ( (IsAutoFit() || IsFitToSize()) && !mbInDownScale
)
1875 assert(mpEditingOutliner
);
1876 mbInDownScale
= true;
1878 // Need to reset scaling so it searches for the fitting size again
1879 mpEditingOutliner
->resetScalingParameters();
1881 // sucks that we cannot disable paints via
1882 // mpEditingOutliner->SetUpdateMode(FALSE) - but EditEngine skips
1883 // formatting as well, then.
1884 setupAutoFitText(*mpEditingOutliner
);
1885 mbInDownScale
= false;
1889 /* Begin chaining code */
1891 // XXX: Make it a method somewhere?
1892 static SdrObject
*ImpGetObjByName(SdrObjList
const *pObjList
, std::u16string_view aObjName
)
1894 // scan the whole list
1895 for (const rtl::Reference
<SdrObject
>& pCurObj
: *pObjList
)
1896 if (pCurObj
->GetName() == aObjName
)
1897 return pCurObj
.get();
1902 // XXX: Make it a (private) method of SdrTextObj
1903 static void ImpUpdateChainLinks(SdrTextObj
*pTextObj
, std::u16string_view aNextLinkName
)
1905 // XXX: Current implementation constraints text boxes to be on the same page
1908 if (aNextLinkName
.empty()) {
1909 pTextObj
->SetNextLinkInChain(nullptr);
1913 SdrPage
*pPage(pTextObj
->getSdrPageFromSdrObject());
1915 SdrTextObj
*pNextTextObj
= DynCastSdrTextObj
1916 (ImpGetObjByName(pPage
, aNextLinkName
));
1917 if (!pNextTextObj
) {
1918 SAL_INFO("svx.chaining", "[CHAINING] Can't find object as next link.");
1922 pTextObj
->SetNextLinkInChain(pNextTextObj
);
1925 bool SdrTextObj::IsChainable() const
1928 const SfxItemSet
& rSet
= GetObjectItemSet();
1929 OUString aNextLinkName
= rSet
.Get(SDRATTR_TEXT_CHAINNEXTNAME
).GetValue();
1931 // Update links if any inconsistency is found
1932 bool bNextLinkUnsetYet
= !aNextLinkName
.isEmpty() && !mpNextInChain
;
1933 bool bInconsistentNextLink
= mpNextInChain
&& mpNextInChain
->GetName() != aNextLinkName
;
1934 // if the link is not set despite there should be one OR if it has changed
1935 if (bNextLinkUnsetYet
|| bInconsistentNextLink
) {
1936 ImpUpdateChainLinks(const_cast<SdrTextObj
*>(this), aNextLinkName
);
1939 return !aNextLinkName
.isEmpty(); // XXX: Should we also check for GetNilChainingEvent? (see old code below)
1942 // Check that no overflow is going on
1943 if (!GetTextChain() || GetTextChain()->GetNilChainingEvent(this))
1948 void SdrTextObj::onChainingEvent()
1950 if (!mpEditingOutliner
)
1953 // Outliner for text transfer
1954 SdrOutliner
&aDrawOutliner
= ImpGetDrawOutliner();
1956 EditingTextChainFlow
aTxtChainFlow(this);
1957 aTxtChainFlow
.CheckForFlowEvents(mpEditingOutliner
);
1959 if (aTxtChainFlow
.IsOverflow()) {
1960 SAL_INFO("svx.chaining", "[CHAINING] Overflow going on");
1961 // One outliner is for non-overflowing text, the other for overflowing text
1962 // We remove text directly from the editing outliner
1963 aTxtChainFlow
.ExecuteOverflow(mpEditingOutliner
, &aDrawOutliner
);
1964 } else if (aTxtChainFlow
.IsUnderflow()) {
1965 SAL_INFO("svx.chaining", "[CHAINING] Underflow going on");
1966 // underflow-induced overflow
1967 aTxtChainFlow
.ExecuteUnderflow(&aDrawOutliner
);
1968 bool bIsOverflowFromUnderflow
= aTxtChainFlow
.IsOverflow();
1970 if (bIsOverflowFromUnderflow
) {
1971 SAL_INFO("svx.chaining", "[CHAINING] Overflow going on (underflow induced)");
1972 // prevents infinite loops when setting text for editing outliner
1973 aTxtChainFlow
.ExecuteOverflow(&aDrawOutliner
, &aDrawOutliner
);
1978 SdrTextObj
* SdrTextObj::GetNextLinkInChain() const
1982 return GetTextChain()->GetNextLink(this);
1987 return mpNextInChain
;
1990 void SdrTextObj::SetNextLinkInChain(SdrTextObj
*pNextObj
)
1992 // Basically a doubly linked list implementation
1994 SdrTextObj
*pOldNextObj
= mpNextInChain
;
1996 // Replace next link
1997 mpNextInChain
= pNextObj
;
1998 // Deal with old next link's prev link
2000 pOldNextObj
->mpPrevInChain
= nullptr;
2003 // Deal with new next link's prev link
2004 if (mpNextInChain
) {
2005 // If there is a prev already at all and this is not already the current object
2006 if (mpNextInChain
->mpPrevInChain
&&
2007 mpNextInChain
->mpPrevInChain
!= this)
2008 mpNextInChain
->mpPrevInChain
->mpNextInChain
= nullptr;
2009 mpNextInChain
->mpPrevInChain
= this;
2012 // TODO: Introduce check for circular chains
2016 SdrTextObj
* SdrTextObj::GetPrevLinkInChain() const
2020 return GetTextChain()->GetPrevLink(this);
2025 return mpPrevInChain
;
2028 bool SdrTextObj::GetPreventChainable() const
2030 // Prevent chaining it 1) during dragging && 2) when we are editing next link
2031 return mbIsUnchainableClone
|| (GetNextLinkInChain() && GetNextLinkInChain()->IsInEditMode());
2034 rtl::Reference
<SdrObject
> SdrTextObj::getFullDragClone() const
2036 rtl::Reference
<SdrObject
> pClone
= SdrAttrObj::getFullDragClone();
2037 SdrTextObj
*pTextObjClone
= DynCastSdrTextObj(pClone
.get());
2038 if (pTextObjClone
!= nullptr) {
2039 // Avoid transferring of text for chainable object during dragging
2040 pTextObjClone
->mbIsUnchainableClone
= true;
2046 /* End chaining code */
2048 /** returns the currently active text. */
2049 SdrText
* SdrTextObj::getActiveText() const
2052 return getText( 0 );
2054 return mxText
.get();
2057 /** returns the nth available text. */
2058 SdrText
* SdrTextObj::getText( sal_Int32 nIndex
) const
2063 const_cast< SdrTextObj
* >(this)->mxText
= new SdrText( *const_cast< SdrTextObj
* >(this) );
2064 return mxText
.get();
2072 /** returns the number of texts available for this object. */
2073 sal_Int32
SdrTextObj::getTextCount() const
2078 /** changes the current active text */
2079 void SdrTextObj::setActiveText( sal_Int32
/*nIndex*/ )
2083 /** returns the index of the text that contains the given point or -1 */
2084 sal_Int32
SdrTextObj::CheckTextHit(const Point
& /*rPnt*/) const
2089 void SdrTextObj::SetObjectItemNoBroadcast(const SfxPoolItem
& rItem
)
2091 static_cast< sdr::properties::TextProperties
& >(GetProperties()).SetObjectItemNoBroadcast(rItem
);
2095 // The concept of the text object:
2096 // ~~~~~~~~~~~~~~~~~~~~~~~~
2097 // Attributes/Variations:
2098 // - bool text frame / graphics object with caption
2099 // - bool FontWork (if it is not a text frame and not a ContourTextFrame)
2100 // - bool ContourTextFrame (if it is not a text frame and not Fontwork)
2101 // - long rotation angle (if it is not FontWork)
2102 // - long text frame margins (if it is not FontWork)
2103 // - bool FitToSize (if it is not FontWork)
2104 // - bool AutoGrowingWidth/Height (if it is not FitToSize and not FontWork)
2105 // - long Min/MaxFrameWidth/Height (if AutoGrowingWidth/Height)
2106 // - enum horizontal text anchoring left,center,right,justify/block,Stretch(ni)
2107 // - enum vertical text anchoring top, middle, bottom, block, stretch(ni)
2108 // - enum ticker text (if it is not FontWork)
2110 // Every derived object is either a text frame (mbTextFrame=true)
2111 // or a drawing object with a caption (mbTextFrame=false).
2113 // Default anchoring for text frames:
2114 // SDRTEXTHORZADJUST_BLOCK, SDRTEXTVERTADJUST_TOP
2115 // = static Pool defaults
2116 // Default anchoring for drawing objects with a caption:
2117 // SDRTEXTHORZADJUST_CENTER, SDRTEXTVERTADJUST_CENTER
2118 // via "hard" attribution of SdrAttrObj
2120 // Every object derived from SdrTextObj must return an "UnrotatedSnapRect"
2121 // (->TakeUnrotatedSnapRect()) (the reference point for the rotation is the top
2122 // left of the rectangle (maGeo.nRotationAngle)) which is the basis for anchoring
2123 // text. We then subtract the text frame margins from this rectangle, as a re-
2124 // sult we get the anchoring area (->TakeTextAnchorRect()). Within this area, we
2125 // calculate the anchoring point and the painting area, depending on the hori-
2126 // zontal and vertical adjustment of the text (SdrTextVertAdjust,
2127 // SdrTextHorzAdjust).
2128 // In the case of drawing objects with a caption the painting area might well
2129 // be larger than the anchoring area, for text frames on the other hand, it is
2130 // always of the same or a smaller size (except when there are negative text
2133 // FitToSize takes priority over text anchoring and AutoGrowHeight/Width. When
2134 // FitToSize is turned on, the painting area is always equal to the anchoring
2135 // area. Additionally, FitToSize doesn't allow automatic line breaks.
2137 // ContourTextFrame:
2138 // - long rotation angle
2139 // - long text frame margins (maybe later)
2140 // - bool FitToSize (maybe later)
2141 // - bool AutoGrowingWidth/Height (maybe much later)
2142 // - long Min/MaxFrameWidth/Height (maybe much later)
2143 // - enum horizontal text anchoring (maybe later, for now: left, centered)
2144 // - enum vertical text anchoring (maybe later, for now: top)
2145 // - enum ticker text (maybe later, maybe even with correct clipping)
2147 // When making changes, check these:
2152 // - Printing, Saving, Painting in neighboring View while editing
2153 // - ModelChanged (e. g. through a neighboring View or rulers) while editing
2154 // - FillColorChanged while editing
2155 // - and many more...
2158 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */