bump product version to 5.0.4.1
[LibreOffice.git] / svx / source / svdraw / svdotext.cxx
blob47696fd2820401de6826466430f250d4b335244b
1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 /*
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 <svx/svdotext.hxx>
23 #include <svx/svdpagv.hxx>
24 #include <svx/svdview.hxx>
25 #include <svx/svdpage.hxx>
26 #include <svx/svdetc.hxx>
27 #include <svx/svdoutl.hxx>
28 #include <svx/svdmodel.hxx>
29 #include "svdglob.hxx"
30 #include "svx/svdstr.hrc"
31 #include <editeng/writingmodeitem.hxx>
32 #include <svx/sdtfchim.hxx>
33 #include <svtools/colorcfg.hxx>
34 #include <editeng/editdata.hxx>
35 #include <editeng/eeitem.hxx>
36 #include <editeng/editstat.hxx>
37 #include <editeng/outlobj.hxx>
38 #include <editeng/editobj.hxx>
39 #include <editeng/outliner.hxx>
40 #include <editeng/fhgtitem.hxx>
41 #include <svl/itempool.hxx>
42 #include <editeng/adjustitem.hxx>
43 #include <editeng/flditem.hxx>
44 #include <svx/xftouit.hxx>
45 #include <tools/helpers.hxx>
46 #include <svx/xflgrit.hxx>
47 #include <svx/svdpool.hxx>
48 #include <svx/xflclit.hxx>
49 #include <svl/style.hxx>
50 #include <editeng/editeng.hxx>
51 #include <svl/itemiter.hxx>
52 #include <sdr/properties/textproperties.hxx>
53 #include <vcl/metaact.hxx>
54 #include <svx/sdr/contact/viewcontactoftextobj.hxx>
55 #include <basegfx/tuple/b2dtuple.hxx>
56 #include <basegfx/matrix/b2dhommatrix.hxx>
57 #include <basegfx/polygon/b2dpolygon.hxx>
58 #include <drawinglayer/geometry/viewinformation2d.hxx>
59 #include <vcl/virdev.hxx>
60 #include <basegfx/matrix/b2dhommatrixtools.hxx>
61 #include "svdconv.hxx"
63 using namespace com::sun::star;
66 // BaseProperties section
68 sdr::properties::BaseProperties* SdrTextObj::CreateObjectSpecificProperties()
70 return new sdr::properties::TextProperties(*this);
74 // DrawContact section
76 sdr::contact::ViewContact* SdrTextObj::CreateObjectSpecificViewContact()
78 return new sdr::contact::ViewContactOfTextObj(*this);
83 TYPEINIT1(SdrTextObj,SdrAttrObj);
85 SdrTextObj::SdrTextObj()
86 : SdrAttrObj(),
87 mpText(NULL),
88 pEdtOutl(NULL),
89 pFormTextBoundRect(NULL),
90 eTextKind(OBJ_TEXT)
92 bTextSizeDirty=false;
93 bTextFrame=false;
94 bPortionInfoChecked=false;
95 bNoShear=false;
96 bNoRotate=false;
97 bNoMirror=false;
98 bDisableAutoWidthOnDragging=false;
100 mbInEditMode = false;
101 mbTextHidden = false;
102 mbTextAnimationAllowed = true;
103 maTextEditOffset = Point(0, 0);
105 // #i25616#
106 mbSupportTextIndentingOnLineWidthChange = true;
107 mbInDownScale = false;
110 SdrTextObj::SdrTextObj(const Rectangle& rNewRect)
111 : SdrAttrObj(),
112 maRect(rNewRect),
113 mpText(NULL),
114 pEdtOutl(NULL),
115 pFormTextBoundRect(NULL),
116 eTextKind(OBJ_TEXT)
118 bTextSizeDirty=false;
119 bTextFrame=false;
120 bPortionInfoChecked=false;
121 bNoShear=false;
122 bNoRotate=false;
123 bNoMirror=false;
124 bDisableAutoWidthOnDragging=false;
125 ImpJustifyRect(maRect);
127 mbInEditMode = false;
128 mbTextHidden = false;
129 mbTextAnimationAllowed = true;
130 mbInDownScale = false;
131 maTextEditOffset = Point(0, 0);
133 // #i25616#
134 mbSupportTextIndentingOnLineWidthChange = true;
137 SdrTextObj::SdrTextObj(SdrObjKind eNewTextKind)
138 : SdrAttrObj(),
139 mpText(NULL),
140 pEdtOutl(NULL),
141 pFormTextBoundRect(NULL),
142 eTextKind(eNewTextKind)
144 bTextSizeDirty=false;
145 bTextFrame=true;
146 bPortionInfoChecked=false;
147 bNoShear=true;
148 bNoRotate=false;
149 bNoMirror=true;
150 bDisableAutoWidthOnDragging=false;
152 mbInEditMode = false;
153 mbTextHidden = false;
154 mbTextAnimationAllowed = true;
155 mbInDownScale = false;
156 maTextEditOffset = Point(0, 0);
158 // #i25616#
159 mbSupportTextIndentingOnLineWidthChange = true;
162 SdrTextObj::SdrTextObj(SdrObjKind eNewTextKind, const Rectangle& rNewRect)
163 : SdrAttrObj(),
164 maRect(rNewRect),
165 mpText(NULL),
166 pEdtOutl(NULL),
167 pFormTextBoundRect(NULL),
168 eTextKind(eNewTextKind)
170 bTextSizeDirty=false;
171 bTextFrame=true;
172 bPortionInfoChecked=false;
173 bNoShear=true;
174 bNoRotate=false;
175 bNoMirror=true;
176 bDisableAutoWidthOnDragging=false;
177 ImpJustifyRect(maRect);
179 mbInEditMode = false;
180 mbTextHidden = false;
181 mbTextAnimationAllowed = true;
182 mbInDownScale = false;
183 maTextEditOffset = Point(0, 0);
185 // #i25616#
186 mbSupportTextIndentingOnLineWidthChange = true;
189 SdrTextObj::~SdrTextObj()
191 if( pModel )
193 SdrOutliner& rOutl = pModel->GetHitTestOutliner();
194 if( rOutl.GetTextObj() == this )
195 rOutl.SetTextObj( NULL );
198 delete mpText;
200 delete pFormTextBoundRect;
202 ImpLinkAbmeldung();
205 void SdrTextObj::FitFrameToTextSize()
207 DBG_ASSERT(pModel!=NULL,"SdrTextObj::FitFrameToTextSize(): pModel=NULL!");
208 ImpJustifyRect(maRect);
210 SdrText* pText = getActiveText();
211 if( pText!=NULL && pText->GetOutlinerParaObject() && pModel!=NULL)
213 SdrOutliner& rOutliner=ImpGetDrawOutliner();
214 rOutliner.SetPaperSize(Size(maRect.Right()-maRect.Left(),maRect.Bottom()-maRect.Top()));
215 rOutliner.SetUpdateMode(true);
216 rOutliner.SetText(*pText->GetOutlinerParaObject());
217 Size aNewSize(rOutliner.CalcTextSize());
218 rOutliner.Clear();
219 aNewSize.Width()++; // because of possible rounding errors
220 aNewSize.Width()+=GetTextLeftDistance()+GetTextRightDistance();
221 aNewSize.Height()+=GetTextUpperDistance()+GetTextLowerDistance();
222 Rectangle aNewRect(maRect);
223 aNewRect.SetSize(aNewSize);
224 ImpJustifyRect(aNewRect);
225 if (aNewRect!=maRect) {
226 SetLogicRect(aNewRect);
231 void SdrTextObj::NbcSetText(const OUString& rStr)
233 SdrOutliner& rOutliner=ImpGetDrawOutliner();
234 rOutliner.SetStyleSheet( 0, GetStyleSheet());
235 rOutliner.SetUpdateMode(true);
236 rOutliner.SetText(rStr,rOutliner.GetParagraph( 0 ));
237 OutlinerParaObject* pNewText=rOutliner.CreateParaObject();
238 Size aSiz(rOutliner.CalcTextSize());
239 rOutliner.Clear();
240 NbcSetOutlinerParaObject(pNewText);
241 aTextSize=aSiz;
242 bTextSizeDirty=false;
245 void SdrTextObj::SetText(const OUString& rStr)
247 Rectangle aBoundRect0; if (pUserCall!=NULL) aBoundRect0=GetLastBoundRect();
248 NbcSetText(rStr);
249 SetChanged();
250 BroadcastObjectChange();
251 SendUserCall(SDRUSERCALL_RESIZE,aBoundRect0);
254 void SdrTextObj::NbcSetText(SvStream& rInput, const OUString& rBaseURL, sal_uInt16 eFormat)
256 SdrOutliner& rOutliner=ImpGetDrawOutliner();
257 rOutliner.SetStyleSheet( 0, GetStyleSheet());
258 rOutliner.Read(rInput,rBaseURL,eFormat);
259 OutlinerParaObject* pNewText=rOutliner.CreateParaObject();
260 rOutliner.SetUpdateMode(true);
261 Size aSiz(rOutliner.CalcTextSize());
262 rOutliner.Clear();
263 NbcSetOutlinerParaObject(pNewText);
264 aTextSize=aSiz;
265 bTextSizeDirty=false;
268 void SdrTextObj::SetText(SvStream& rInput, const OUString& rBaseURL, sal_uInt16 eFormat)
270 Rectangle aBoundRect0; if (pUserCall!=NULL) aBoundRect0=GetLastBoundRect();
271 NbcSetText(rInput,rBaseURL,eFormat);
272 SetChanged();
273 BroadcastObjectChange();
274 SendUserCall(SDRUSERCALL_RESIZE,aBoundRect0);
277 const Size& SdrTextObj::GetTextSize() const
279 if (bTextSizeDirty)
281 Size aSiz;
282 SdrText* pText = getActiveText();
283 if( pText && pText->GetOutlinerParaObject ())
285 SdrOutliner& rOutliner=ImpGetDrawOutliner();
286 rOutliner.SetText(*pText->GetOutlinerParaObject());
287 rOutliner.SetUpdateMode(true);
288 aSiz=rOutliner.CalcTextSize();
289 rOutliner.Clear();
291 // casting to nonconst twice
292 const_cast<SdrTextObj*>(this)->aTextSize=aSiz;
293 const_cast<SdrTextObj*>(this)->bTextSizeDirty=false;
295 return aTextSize;
298 bool SdrTextObj::IsAutoGrowHeight() const
300 if(!bTextFrame)
301 return false; // AutoGrow only together with TextFrames
303 const SfxItemSet& rSet = GetObjectItemSet();
304 bool bRet = static_cast<const SdrOnOffItem&>(rSet.Get(SDRATTR_TEXT_AUTOGROWHEIGHT)).GetValue();
306 if(bRet)
308 SdrTextAniKind eAniKind = static_cast<const SdrTextAniKindItem&>(rSet.Get(SDRATTR_TEXT_ANIKIND)).GetValue();
310 if(eAniKind == SDRTEXTANI_SCROLL || eAniKind == SDRTEXTANI_ALTERNATE || eAniKind == SDRTEXTANI_SLIDE)
312 SdrTextAniDirection eDirection = static_cast<const SdrTextAniDirectionItem&>(rSet.Get(SDRATTR_TEXT_ANIDIRECTION)).GetValue();
314 if(eDirection == SDRTEXTANI_UP || eDirection == SDRTEXTANI_DOWN)
316 bRet = false;
320 return bRet;
323 bool SdrTextObj::IsAutoGrowWidth() const
325 if(!bTextFrame)
326 return false; // AutoGrow only together with TextFrames
328 const SfxItemSet& rSet = GetObjectItemSet();
329 bool bRet = static_cast<const SdrOnOffItem&>(rSet.Get(SDRATTR_TEXT_AUTOGROWWIDTH)).GetValue();
331 bool bInEditMOde = IsInEditMode();
333 if(!bInEditMOde && bRet)
335 SdrTextAniKind eAniKind = static_cast<const SdrTextAniKindItem&>(rSet.Get(SDRATTR_TEXT_ANIKIND)).GetValue();
337 if(eAniKind == SDRTEXTANI_SCROLL || eAniKind == SDRTEXTANI_ALTERNATE || eAniKind == SDRTEXTANI_SLIDE)
339 SdrTextAniDirection eDirection = static_cast<const SdrTextAniDirectionItem&>(rSet.Get(SDRATTR_TEXT_ANIDIRECTION)).GetValue();
341 if(eDirection == SDRTEXTANI_LEFT || eDirection == SDRTEXTANI_RIGHT)
343 bRet = false;
347 return bRet;
350 SdrTextHorzAdjust SdrTextObj::GetTextHorizontalAdjust() const
352 return GetTextHorizontalAdjust(GetObjectItemSet());
355 SdrTextHorzAdjust SdrTextObj::GetTextHorizontalAdjust(const SfxItemSet& rSet) const
357 if(IsContourTextFrame())
358 return SDRTEXTHORZADJUST_BLOCK;
360 SdrTextHorzAdjust eRet = static_cast<const SdrTextHorzAdjustItem&>(rSet.Get(SDRATTR_TEXT_HORZADJUST)).GetValue();
362 bool bInEditMode = IsInEditMode();
364 if(!bInEditMode && eRet == SDRTEXTHORZADJUST_BLOCK)
366 SdrTextAniKind eAniKind = static_cast<const SdrTextAniKindItem&>(rSet.Get(SDRATTR_TEXT_ANIKIND)).GetValue();
368 if(eAniKind == SDRTEXTANI_SCROLL || eAniKind == SDRTEXTANI_ALTERNATE || eAniKind == SDRTEXTANI_SLIDE)
370 SdrTextAniDirection eDirection = static_cast<const SdrTextAniDirectionItem&>(rSet.Get(SDRATTR_TEXT_ANIDIRECTION)).GetValue();
372 if(eDirection == SDRTEXTANI_LEFT || eDirection == SDRTEXTANI_RIGHT)
374 eRet = SDRTEXTHORZADJUST_LEFT;
379 return eRet;
380 } // defaults: BLOCK (justify) for text frame, CENTER for captions of drawing objects
382 SdrTextVertAdjust SdrTextObj::GetTextVerticalAdjust() const
384 return GetTextVerticalAdjust(GetObjectItemSet());
387 SdrTextVertAdjust SdrTextObj::GetTextVerticalAdjust(const SfxItemSet& rSet) const
389 if(IsContourTextFrame())
390 return SDRTEXTVERTADJUST_TOP;
392 // Take care for vertical text animation here
393 SdrTextVertAdjust eRet = static_cast<const SdrTextVertAdjustItem&>(rSet.Get(SDRATTR_TEXT_VERTADJUST)).GetValue();
394 bool bInEditMode = IsInEditMode();
396 // Take care for vertical text animation here
397 if(!bInEditMode && eRet == SDRTEXTVERTADJUST_BLOCK)
399 SdrTextAniKind eAniKind = static_cast<const SdrTextAniKindItem&>(rSet.Get(SDRATTR_TEXT_ANIKIND)).GetValue();
401 if(eAniKind == SDRTEXTANI_SCROLL || eAniKind == SDRTEXTANI_ALTERNATE || eAniKind == SDRTEXTANI_SLIDE)
403 SdrTextAniDirection eDirection = static_cast<const SdrTextAniDirectionItem&>(rSet.Get(SDRATTR_TEXT_ANIDIRECTION)).GetValue();
405 if(eDirection == SDRTEXTANI_LEFT || eDirection == SDRTEXTANI_RIGHT)
407 eRet = SDRTEXTVERTADJUST_TOP;
412 return eRet;
413 } // defaults: TOP for text frame, CENTER for captions of drawing objects
415 void SdrTextObj::ImpJustifyRect(Rectangle& rRect)
417 if (!rRect.IsEmpty()) {
418 rRect.Justify();
419 if (rRect.Left()==rRect.Right()) rRect.Right()++;
420 if (rRect.Top()==rRect.Bottom()) rRect.Bottom()++;
424 void SdrTextObj::ImpCheckShear()
426 if (bNoShear && aGeo.nShearAngle!=0) {
427 aGeo.nShearAngle=0;
428 aGeo.nTan=0;
432 void SdrTextObj::TakeObjInfo(SdrObjTransformInfoRec& rInfo) const
434 bool bNoTextFrame=!IsTextFrame();
435 rInfo.bResizeFreeAllowed=bNoTextFrame || aGeo.nRotationAngle%9000==0;
436 rInfo.bResizePropAllowed=true;
437 rInfo.bRotateFreeAllowed=true;
438 rInfo.bRotate90Allowed =true;
439 rInfo.bMirrorFreeAllowed=bNoTextFrame;
440 rInfo.bMirror45Allowed =bNoTextFrame;
441 rInfo.bMirror90Allowed =bNoTextFrame;
443 // allow transparency
444 rInfo.bTransparenceAllowed = true;
446 // gradient depends on fillstyle
447 drawing::FillStyle eFillStyle = static_cast<const XFillStyleItem&>(GetObjectItem(XATTR_FILLSTYLE)).GetValue();
448 rInfo.bGradientAllowed = (eFillStyle == drawing::FillStyle_GRADIENT);
449 rInfo.bShearAllowed =bNoTextFrame;
450 rInfo.bEdgeRadiusAllowed=true;
451 bool bCanConv=ImpCanConvTextToCurve();
452 rInfo.bCanConvToPath =bCanConv;
453 rInfo.bCanConvToPoly =bCanConv;
454 rInfo.bCanConvToPathLineToArea=bCanConv;
455 rInfo.bCanConvToPolyLineToArea=bCanConv;
456 rInfo.bCanConvToContour = (rInfo.bCanConvToPoly || LineGeometryUsageIsNecessary());
459 sal_uInt16 SdrTextObj::GetObjIdentifier() const
461 return sal_uInt16(eTextKind);
464 bool SdrTextObj::HasTextImpl( SdrOutliner* pOutliner )
466 bool bRet=false;
467 if(pOutliner)
469 Paragraph* p1stPara=pOutliner->GetParagraph( 0 );
470 sal_Int32 nParaCount=pOutliner->GetParagraphCount();
471 if(p1stPara==NULL)
472 nParaCount=0;
474 if(nParaCount==1)
476 // if it is only one paragraph, check if that paragraph is empty
477 if( pOutliner->GetText(p1stPara).isEmpty() )
478 nParaCount = 0;
481 bRet= nParaCount!=0;
483 return bRet;
486 bool SdrTextObj::HasEditText() const
488 return HasTextImpl( pEdtOutl );
491 void SdrTextObj::SetPage(SdrPage* pNewPage)
493 bool bRemove=pNewPage==NULL && pPage!=NULL;
494 bool bInsert=pNewPage!=NULL && pPage==NULL;
495 bool bLinked=IsLinkedText();
497 if (bLinked && bRemove) {
498 ImpLinkAbmeldung();
501 SdrAttrObj::SetPage(pNewPage);
503 if (bLinked && bInsert) {
504 ImpLinkAnmeldung();
508 void SdrTextObj::SetModel(SdrModel* pNewModel)
510 SdrModel* pOldModel=pModel;
511 bool bLinked=IsLinkedText();
512 bool bChg=pNewModel!=pModel;
514 if (bLinked && bChg)
516 ImpLinkAbmeldung();
519 SdrAttrObj::SetModel(pNewModel);
521 if( bChg )
523 if( pNewModel != 0 && pOldModel != 0 )
524 SetTextSizeDirty();
526 sal_Int32 nCount = getTextCount();
527 for( sal_Int32 nText = 0; nText < nCount; nText++ )
529 SdrText* pText = getText( nText );
530 if( pText )
531 pText->SetModel( pNewModel );
535 if (bLinked && bChg)
537 ImpLinkAnmeldung();
541 bool SdrTextObj::NbcSetEckenradius(long nRad)
543 SetObjectItem(makeSdrEckenradiusItem(nRad));
544 return true;
547 // #115391# This implementation is based on the object size (aRect) and the
548 // states of IsAutoGrowWidth/Height to correctly set TextMinFrameWidth/Height
549 void SdrTextObj::AdaptTextMinSize()
551 if (!bTextFrame)
552 // Only do this for text frame.
553 return;
555 if (pModel && pModel->IsPasteResize())
556 // Don't do this during paste resize.
557 return;
559 const bool bW = IsAutoGrowWidth();
560 const bool bH = IsAutoGrowHeight();
562 if (!bW && !bH)
563 // No auto grow requested. Bail out.
564 return;
566 SfxItemSet aSet(
567 *GetObjectItemSet().GetPool(),
568 SDRATTR_TEXT_MINFRAMEHEIGHT, SDRATTR_TEXT_AUTOGROWHEIGHT,
569 SDRATTR_TEXT_MINFRAMEWIDTH, SDRATTR_TEXT_AUTOGROWWIDTH, // contains SDRATTR_TEXT_MAXFRAMEWIDTH
570 0, 0);
572 if(bW)
574 // Set minimum width.
575 const long nDist = GetTextLeftDistance() + GetTextRightDistance();
576 const long nW = std::max<long>(0, maRect.GetWidth() - 1 - nDist); // text width without margins
578 aSet.Put(makeSdrTextMinFrameWidthItem(nW));
580 if(!IsVerticalWriting() && bDisableAutoWidthOnDragging)
582 bDisableAutoWidthOnDragging = true;
583 aSet.Put(makeSdrTextAutoGrowWidthItem(false));
587 if(bH)
589 // Set Minimum height.
590 const long nDist = GetTextUpperDistance() + GetTextLowerDistance();
591 const long nH = std::max<long>(0, maRect.GetHeight() - 1 - nDist); // text height without margins
593 aSet.Put(makeSdrTextMinFrameHeightItem(nH));
595 if(IsVerticalWriting() && bDisableAutoWidthOnDragging)
597 bDisableAutoWidthOnDragging = false;
598 aSet.Put(makeSdrTextAutoGrowHeightItem(false));
602 SetObjectItemSet(aSet);
605 void SdrTextObj::ImpSetContourPolygon( SdrOutliner& rOutliner, Rectangle& rAnchorRect, bool bLineWidth ) const
607 basegfx::B2DPolyPolygon aXorPolyPolygon(TakeXorPoly());
608 basegfx::B2DPolyPolygon* pContourPolyPolygon = 0L;
609 basegfx::B2DHomMatrix aMatrix(basegfx::tools::createTranslateB2DHomMatrix(
610 -rAnchorRect.Left(), -rAnchorRect.Top()));
612 if(aGeo.nRotationAngle)
614 // Unrotate!
615 aMatrix.rotate(-aGeo.nRotationAngle * nPi180);
618 aXorPolyPolygon.transform(aMatrix);
620 if( bLineWidth )
622 // Take line width into account.
623 // When doing the hit test, avoid this. (Performance!)
624 pContourPolyPolygon = new basegfx::B2DPolyPolygon();
626 // test if shadow needs to be avoided for TakeContour()
627 const SfxItemSet& rSet = GetObjectItemSet();
628 bool bShadowOn = static_cast<const SdrOnOffItem&>(rSet.Get(SDRATTR_SHADOW)).GetValue();
630 // #i33696#
631 // Remember TextObject currently set at the DrawOutliner, it WILL be
632 // replaced during calculating the outline since it uses an own paint
633 // and that one uses the DrawOutliner, too.
634 const SdrTextObj* pLastTextObject = rOutliner.GetTextObj();
636 if(bShadowOn)
638 // force shadow off
639 SdrObject* pCopy = Clone();
640 pCopy->SetMergedItem(makeSdrShadowItem(false));
641 *pContourPolyPolygon = pCopy->TakeContour();
642 SdrObject::Free( pCopy );
644 else
646 *pContourPolyPolygon = TakeContour();
649 // #i33696#
650 // restore remembered text object
651 if(pLastTextObject != rOutliner.GetTextObj())
653 rOutliner.SetTextObj(pLastTextObject);
656 pContourPolyPolygon->transform(aMatrix);
659 rOutliner.SetPolygon(aXorPolyPolygon, pContourPolyPolygon);
660 delete pContourPolyPolygon;
663 void SdrTextObj::TakeUnrotatedSnapRect(Rectangle& rRect) const
665 rRect=maRect;
668 void SdrTextObj::TakeTextAnchorRect(Rectangle& rAnchorRect) const
670 long nLeftDist=GetTextLeftDistance();
671 long nRightDist=GetTextRightDistance();
672 long nUpperDist=GetTextUpperDistance();
673 long nLowerDist=GetTextLowerDistance();
674 Rectangle aAnkRect(maRect); // the rectangle in which we anchor
675 bool bFrame=IsTextFrame();
676 if (!bFrame) {
677 TakeUnrotatedSnapRect(aAnkRect);
679 Point aRotateRef(aAnkRect.TopLeft());
680 aAnkRect.Left()+=nLeftDist;
681 aAnkRect.Top()+=nUpperDist;
682 aAnkRect.Right()-=nRightDist;
683 aAnkRect.Bottom()-=nLowerDist;
685 // Since sizes may be bigger than the object bounds it is necessary to
686 // justify the rect now.
687 ImpJustifyRect(aAnkRect);
689 if (bFrame) {
690 // TODO: Optimize this.
691 if (aAnkRect.GetWidth()<2) aAnkRect.Right()=aAnkRect.Left()+1; // minimum size h and v: 2 px
692 if (aAnkRect.GetHeight()<2) aAnkRect.Bottom()=aAnkRect.Top()+1;
694 if (aGeo.nRotationAngle!=0) {
695 Point aTmpPt(aAnkRect.TopLeft());
696 RotatePoint(aTmpPt,aRotateRef,aGeo.nSin,aGeo.nCos);
697 aTmpPt-=aAnkRect.TopLeft();
698 aAnkRect.Move(aTmpPt.X(),aTmpPt.Y());
700 rAnchorRect=aAnkRect;
703 void SdrTextObj::TakeTextRect( SdrOutliner& rOutliner, Rectangle& rTextRect, bool bNoEditText,
704 Rectangle* pAnchorRect, bool bLineWidth ) const
706 Rectangle aAnkRect; // the rectangle in which we anchor
707 TakeTextAnchorRect(aAnkRect);
708 SdrTextVertAdjust eVAdj=GetTextVerticalAdjust();
709 SdrTextHorzAdjust eHAdj=GetTextHorizontalAdjust();
710 SdrTextAniKind eAniKind=GetTextAniKind();
711 SdrTextAniDirection eAniDirection=GetTextAniDirection();
713 bool bFitToSize(IsFitToSize());
714 bool bContourFrame=IsContourTextFrame();
716 bool bFrame=IsTextFrame();
717 EEControlBits nStat0=rOutliner.GetControlWord();
718 Size aNullSize;
719 if (!bContourFrame)
721 rOutliner.SetControlWord(nStat0|EEControlBits::AUTOPAGESIZE);
722 rOutliner.SetMinAutoPaperSize(aNullSize);
723 rOutliner.SetMaxAutoPaperSize(Size(1000000,1000000));
726 if (!bFitToSize && !bContourFrame)
728 long nAnkWdt=aAnkRect.GetWidth();
729 long nAnkHgt=aAnkRect.GetHeight();
730 if (bFrame)
732 long nWdt=nAnkWdt;
733 long nHgt=nAnkHgt;
735 bool bInEditMode = IsInEditMode();
737 if (!bInEditMode && (eAniKind==SDRTEXTANI_SCROLL || eAniKind==SDRTEXTANI_ALTERNATE || eAniKind==SDRTEXTANI_SLIDE))
739 // unlimited paper size for ticker text
740 if (eAniDirection==SDRTEXTANI_LEFT || eAniDirection==SDRTEXTANI_RIGHT) nWdt=1000000;
741 if (eAniDirection==SDRTEXTANI_UP || eAniDirection==SDRTEXTANI_DOWN) nHgt=1000000;
744 // #i119885# Do not limit/force height to geometrical frame (vice versa for vertical writing)
745 if(IsVerticalWriting())
747 nWdt = 1000000;
749 else
751 nHgt = 1000000;
754 rOutliner.SetMaxAutoPaperSize(Size(nWdt,nHgt));
757 // New try with _BLOCK for hor and ver after completely
758 // supporting full width for vertical text.
759 if(SDRTEXTHORZADJUST_BLOCK == eHAdj && !IsVerticalWriting())
761 rOutliner.SetMinAutoPaperSize(Size(nAnkWdt, 0));
764 if(SDRTEXTVERTADJUST_BLOCK == eVAdj && IsVerticalWriting())
766 rOutliner.SetMinAutoPaperSize(Size(0, nAnkHgt));
770 rOutliner.SetPaperSize(aNullSize);
771 if (bContourFrame)
772 ImpSetContourPolygon( rOutliner, aAnkRect, bLineWidth );
774 // put text into the outliner, if available from the edit outliner
775 SdrText* pText = getActiveText();
776 OutlinerParaObject* pOutlinerParaObject = pText ? pText->GetOutlinerParaObject() : 0;
777 OutlinerParaObject* pPara = (pEdtOutl && !bNoEditText) ? pEdtOutl->CreateParaObject() : pOutlinerParaObject;
779 if (pPara)
781 bool bHitTest = false;
782 if( pModel )
783 bHitTest = &pModel->GetHitTestOutliner() == &rOutliner;
785 const SdrTextObj* pTestObj = rOutliner.GetTextObj();
786 if( !pTestObj || !bHitTest || pTestObj != this ||
787 pTestObj->GetOutlinerParaObject() != pOutlinerParaObject )
789 if( bHitTest ) // #i33696# take back fix #i27510#
791 rOutliner.SetTextObj( this );
792 rOutliner.SetFixedCellHeight(static_cast<const SdrTextFixedCellHeightItem&>(GetMergedItem(SDRATTR_TEXT_USEFIXEDCELLHEIGHT)).GetValue());
795 rOutliner.SetUpdateMode(true);
796 rOutliner.SetText(*pPara);
799 else
801 rOutliner.SetTextObj( NULL );
804 if (pEdtOutl && !bNoEditText && pPara)
805 delete pPara;
807 rOutliner.SetUpdateMode(true);
808 rOutliner.SetControlWord(nStat0);
810 if( pText )
811 pText->CheckPortionInfo(rOutliner);
813 Point aTextPos(aAnkRect.TopLeft());
814 Size aTextSiz(rOutliner.GetPaperSize()); // GetPaperSize() adds a little tolerance, right?
816 // For draw objects containing text correct hor/ver alignment if text is bigger
817 // than the object itself. Without that correction, the text would always be
818 // formatted to the left edge (or top edge when vertical) of the draw object.
819 if(!IsTextFrame())
821 if(aAnkRect.GetWidth() < aTextSiz.Width() && !IsVerticalWriting())
823 // Horizontal case here. Correct only if eHAdj == SDRTEXTHORZADJUST_BLOCK,
824 // else the alignment is wanted.
825 if(SDRTEXTHORZADJUST_BLOCK == eHAdj)
827 eHAdj = SDRTEXTHORZADJUST_CENTER;
831 if(aAnkRect.GetHeight() < aTextSiz.Height() && IsVerticalWriting())
833 // Vertical case here. Correct only if eHAdj == SDRTEXTVERTADJUST_BLOCK,
834 // else the alignment is wanted.
835 if(SDRTEXTVERTADJUST_BLOCK == eVAdj)
837 eVAdj = SDRTEXTVERTADJUST_CENTER;
842 if (eHAdj==SDRTEXTHORZADJUST_CENTER || eHAdj==SDRTEXTHORZADJUST_RIGHT)
844 long nFreeWdt=aAnkRect.GetWidth()-aTextSiz.Width();
845 if (eHAdj==SDRTEXTHORZADJUST_CENTER)
846 aTextPos.X()+=nFreeWdt/2;
847 if (eHAdj==SDRTEXTHORZADJUST_RIGHT)
848 aTextPos.X()+=nFreeWdt;
850 if (eVAdj==SDRTEXTVERTADJUST_CENTER || eVAdj==SDRTEXTVERTADJUST_BOTTOM)
852 long nFreeHgt=aAnkRect.GetHeight()-aTextSiz.Height();
853 if (eVAdj==SDRTEXTVERTADJUST_CENTER)
854 aTextPos.Y()+=nFreeHgt/2;
855 if (eVAdj==SDRTEXTVERTADJUST_BOTTOM)
856 aTextPos.Y()+=nFreeHgt;
858 if (aGeo.nRotationAngle!=0)
859 RotatePoint(aTextPos,aAnkRect.TopLeft(),aGeo.nSin,aGeo.nCos);
861 if (pAnchorRect)
862 *pAnchorRect=aAnkRect;
864 // rTextRect might not be correct in some cases at ContourFrame
865 rTextRect=Rectangle(aTextPos,aTextSiz);
866 if (bContourFrame)
867 rTextRect=aAnkRect;
870 OutlinerParaObject* SdrTextObj::GetEditOutlinerParaObject() const
872 OutlinerParaObject* pPara=NULL;
873 if( HasTextImpl( pEdtOutl ) )
875 sal_Int32 nParaCount = pEdtOutl->GetParagraphCount();
876 pPara = pEdtOutl->CreateParaObject(0, nParaCount);
878 return pPara;
881 void SdrTextObj::ImpSetCharStretching(SdrOutliner& rOutliner, const Size& rTextSize, const Size& rShapeSize, Fraction& rFitXKorreg)
883 OutputDevice* pOut = rOutliner.GetRefDevice();
884 bool bNoStretching(false);
886 if(pOut && pOut->GetOutDevType() == OUTDEV_PRINTER)
888 // check whether CharStretching is possible at all
889 GDIMetaFile* pMtf = pOut->GetConnectMetaFile();
890 OUString aTestString(static_cast<sal_Unicode>('J'));
892 if(pMtf && (!pMtf->IsRecord() || pMtf->IsPause()))
893 pMtf = NULL;
895 if(pMtf)
896 pMtf->Pause(true);
898 vcl::Font aFontMerk(pOut->GetFont());
899 vcl::Font aTmpFont( OutputDevice::GetDefaultFont( DefaultFontType::SERIF, LANGUAGE_SYSTEM, GetDefaultFontFlags::OnlyOne ) );
901 aTmpFont.SetSize(Size(0,100));
902 pOut->SetFont(aTmpFont);
903 Size aSize1(pOut->GetTextWidth(aTestString), pOut->GetTextHeight());
904 aTmpFont.SetSize(Size(800,100));
905 pOut->SetFont(aTmpFont);
906 Size aSize2(pOut->GetTextWidth(aTestString), pOut->GetTextHeight());
907 pOut->SetFont(aFontMerk);
909 if(pMtf)
910 pMtf->Pause(false);
912 bNoStretching = (aSize1 == aSize2);
914 #ifdef WNT
915 // Windows zooms the font proportionally when using Size(100,500),
916 // we don't like that.
917 if(aSize2.Height() >= aSize1.Height() * 2)
919 bNoStretching = true;
921 #endif
923 unsigned nLoopCount=0;
924 bool bNoMoreLoop = false;
925 long nXDiff0=0x7FFFFFFF;
926 long nWantWdt=rShapeSize.Width();
927 long nIsWdt=rTextSize.Width();
928 if (nIsWdt==0) nIsWdt=1;
930 long nWantHgt=rShapeSize.Height();
931 long nIsHgt=rTextSize.Height();
932 if (nIsHgt==0) nIsHgt=1;
934 long nXTolPl=nWantWdt/100; // tolerance: +1%
935 long nXTolMi=nWantWdt/25; // tolerance: -4%
936 long nXKorr =nWantWdt/20; // correction scale: 5%
938 long nX=(nWantWdt*100) /nIsWdt; // calculate X stretching
939 long nY=(nWantHgt*100) /nIsHgt; // calculate Y stretching
940 bool bChkX = true;
941 if (bNoStretching) { // might only be possible proportionally
942 if (nX>nY) { nX=nY; bChkX=false; }
943 else { nY=nX; }
946 while (nLoopCount<5 && !bNoMoreLoop) {
947 if (nX<0) nX=-nX;
948 if (nX<1) { nX=1; bNoMoreLoop = true; }
949 if (nX>65535) { nX=65535; bNoMoreLoop = true; }
951 if (nY<0) nY=-nY;
952 if (nY<1) { nY=1; bNoMoreLoop = true; }
953 if (nY>65535) { nY=65535; bNoMoreLoop = true; }
955 // exception, there is no text yet (horizontal case)
956 if(nIsWdt <= 1)
958 nX = nY;
959 bNoMoreLoop = true;
962 // exception, there is no text yet (vertical case)
963 if(nIsHgt <= 1)
965 nY = nX;
966 bNoMoreLoop = true;
969 rOutliner.SetGlobalCharStretching((sal_uInt16)nX,(sal_uInt16)nY);
970 nLoopCount++;
971 Size aSiz(rOutliner.CalcTextSize());
972 long nXDiff=aSiz.Width()-nWantWdt;
973 rFitXKorreg=Fraction(nWantWdt,aSiz.Width());
974 if (((nXDiff>=nXTolMi || !bChkX) && nXDiff<=nXTolPl) || nXDiff==nXDiff0) {
975 bNoMoreLoop = true;
976 } else {
977 // correct stretching factors
978 long nMul=nWantWdt;
979 long nDiv=aSiz.Width();
980 if (std::abs(nXDiff)<=2*nXKorr) {
981 if (nMul>nDiv) nDiv+=(nMul-nDiv)/2; // but only add half of what we calculated,
982 else nMul+=(nDiv-nMul)/2; // because the EditEngine calculates wrongly later on
984 nX=nX*nMul/nDiv;
985 if (bNoStretching) nY=nX;
987 nXDiff0=nXDiff;
991 OUString SdrTextObj::TakeObjNameSingul() const
993 OUString aStr;
995 switch(eTextKind)
997 case OBJ_OUTLINETEXT:
999 aStr = ImpGetResStr(STR_ObjNameSingulOUTLINETEXT);
1000 break;
1003 case OBJ_TITLETEXT :
1005 aStr = ImpGetResStr(STR_ObjNameSingulTITLETEXT);
1006 break;
1009 default:
1011 if(IsLinkedText())
1012 aStr = ImpGetResStr(STR_ObjNameSingulTEXTLNK);
1013 else
1014 aStr = ImpGetResStr(STR_ObjNameSingulTEXT);
1015 break;
1019 OutlinerParaObject* pOutlinerParaObject = GetOutlinerParaObject();
1020 if(pOutlinerParaObject && eTextKind != OBJ_OUTLINETEXT)
1022 // shouldn't currently cause any problems at OUTLINETEXT
1023 OUString aStr2(comphelper::string::stripStart(pOutlinerParaObject->GetTextObject().GetText(0), ' '));
1025 // avoid non expanded text portions in object name
1026 // (second condition is new)
1027 if(!aStr2.isEmpty() && aStr2.indexOf(sal_Unicode(255)) == -1)
1029 // space between ResStr and content text
1030 aStr += " ";
1032 aStr += "\'";
1034 if(aStr2.getLength() > 10)
1036 aStr2 = aStr2.copy(0, 8);
1037 aStr2 += "...";
1040 aStr += aStr2;
1041 aStr += "\'";
1045 OUStringBuffer sName(aStr);
1047 OUString aName(GetName());
1048 if (!aName.isEmpty())
1050 sName.append(' ');
1051 sName.append('\'');
1052 sName.append(aName);
1053 sName.append('\'');
1056 return sName.makeStringAndClear();
1059 OUString SdrTextObj::TakeObjNamePlural() const
1061 OUString sName;
1062 switch (eTextKind) {
1063 case OBJ_OUTLINETEXT: sName=ImpGetResStr(STR_ObjNamePluralOUTLINETEXT); break;
1064 case OBJ_TITLETEXT : sName=ImpGetResStr(STR_ObjNamePluralTITLETEXT); break;
1065 default: {
1066 if (IsLinkedText()) {
1067 sName=ImpGetResStr(STR_ObjNamePluralTEXTLNK);
1068 } else {
1069 sName=ImpGetResStr(STR_ObjNamePluralTEXT);
1071 } break;
1072 } // switch
1073 return sName;
1076 SdrTextObj* SdrTextObj::Clone() const
1078 return CloneHelper< SdrTextObj >();
1081 SdrTextObj& SdrTextObj::operator=(const SdrTextObj& rObj)
1083 if( this == &rObj )
1084 return *this;
1085 // call parent
1086 SdrObject::operator=(rObj);
1088 maRect = rObj.maRect;
1089 aGeo =rObj.aGeo;
1090 eTextKind =rObj.eTextKind;
1091 bTextFrame=rObj.bTextFrame;
1092 aTextSize=rObj.aTextSize;
1093 bTextSizeDirty=rObj.bTextSizeDirty;
1095 // Not all of the necessary parameters were copied yet.
1096 bNoShear = rObj.bNoShear;
1097 bNoRotate = rObj.bNoRotate;
1098 bNoMirror = rObj.bNoMirror;
1099 bDisableAutoWidthOnDragging = rObj.bDisableAutoWidthOnDragging;
1101 OutlinerParaObject* pNewOutlinerParaObject = 0;
1103 SdrText* pText = getActiveText();
1105 if( pText && rObj.HasText() )
1107 const Outliner* pEO=rObj.pEdtOutl;
1108 if (pEO!=NULL)
1110 pNewOutlinerParaObject = pEO->CreateParaObject();
1112 else
1114 pNewOutlinerParaObject = new OutlinerParaObject(*rObj.getActiveText()->GetOutlinerParaObject());
1118 mpText->SetOutlinerParaObject( pNewOutlinerParaObject );
1119 ImpSetTextStyleSheetListeners();
1120 return *this;
1123 basegfx::B2DPolyPolygon SdrTextObj::TakeXorPoly() const
1125 Polygon aPol(maRect);
1126 if (aGeo.nShearAngle!=0) ShearPoly(aPol,maRect.TopLeft(),aGeo.nTan);
1127 if (aGeo.nRotationAngle!=0) RotatePoly(aPol,maRect.TopLeft(),aGeo.nSin,aGeo.nCos);
1129 basegfx::B2DPolyPolygon aRetval;
1130 aRetval.append(aPol.getB2DPolygon());
1131 return aRetval;
1134 basegfx::B2DPolyPolygon SdrTextObj::TakeContour() const
1136 basegfx::B2DPolyPolygon aRetval(SdrAttrObj::TakeContour());
1138 // and now add the BoundRect of the text, if necessary
1139 if ( pModel && GetOutlinerParaObject() && !IsFontwork() && !IsContourTextFrame() )
1141 // using Clone()-Paint() strategy inside TakeContour() leaves a destroyed
1142 // SdrObject as pointer in DrawOutliner. Set *this again in fetching the outliner
1143 // in every case
1144 SdrOutliner& rOutliner=ImpGetDrawOutliner();
1146 Rectangle aAnchor2;
1147 Rectangle aR;
1148 TakeTextRect(rOutliner,aR,false,&aAnchor2);
1149 rOutliner.Clear();
1150 bool bFitToSize(IsFitToSize());
1151 if (bFitToSize) aR=aAnchor2;
1152 Polygon aPol(aR);
1153 if (aGeo.nRotationAngle!=0) RotatePoly(aPol,aR.TopLeft(),aGeo.nSin,aGeo.nCos);
1155 aRetval.append(aPol.getB2DPolygon());
1158 return aRetval;
1161 void SdrTextObj::RecalcSnapRect()
1163 if (aGeo.nRotationAngle!=0 || aGeo.nShearAngle!=0)
1165 Polygon aPol(maRect);
1166 if (aGeo.nShearAngle!=0) ShearPoly(aPol,maRect.TopLeft(),aGeo.nTan);
1167 if (aGeo.nRotationAngle!=0) RotatePoly(aPol,maRect.TopLeft(),aGeo.nSin,aGeo.nCos);
1168 maSnapRect=aPol.GetBoundRect();
1169 } else {
1170 maSnapRect = maRect;
1174 sal_uInt32 SdrTextObj::GetSnapPointCount() const
1176 return 4L;
1179 Point SdrTextObj::GetSnapPoint(sal_uInt32 i) const
1181 Point aP;
1182 switch (i) {
1183 case 0: aP=maRect.TopLeft(); break;
1184 case 1: aP=maRect.TopRight(); break;
1185 case 2: aP=maRect.BottomLeft(); break;
1186 case 3: aP=maRect.BottomRight(); break;
1187 default: aP=maRect.Center(); break;
1189 if (aGeo.nShearAngle!=0) ShearPoint(aP,maRect.TopLeft(),aGeo.nTan);
1190 if (aGeo.nRotationAngle!=0) RotatePoint(aP,maRect.TopLeft(),aGeo.nSin,aGeo.nCos);
1191 return aP;
1194 void SdrTextObj::ImpCheckMasterCachable()
1196 bNotMasterCachable=false;
1198 OutlinerParaObject* pOutlinerParaObject = GetOutlinerParaObject();
1200 if(!bNotVisibleAsMaster && pOutlinerParaObject && pOutlinerParaObject->IsEditDoc() )
1202 const EditTextObject& rText= pOutlinerParaObject->GetTextObject();
1203 bNotMasterCachable=rText.HasField(SvxPageField::StaticClassId());
1204 if( !bNotMasterCachable )
1206 bNotMasterCachable=rText.HasField(SvxHeaderField::StaticClassId());
1207 if( !bNotMasterCachable )
1209 bNotMasterCachable=rText.HasField(SvxFooterField::StaticClassId());
1210 if( !bNotMasterCachable )
1212 bNotMasterCachable=rText.HasField(SvxDateTimeField::StaticClassId());
1219 // Extracted from ImpGetDrawOutliner()
1220 void SdrTextObj::ImpInitDrawOutliner( SdrOutliner& rOutl ) const
1222 rOutl.SetUpdateMode(false);
1223 sal_uInt16 nOutlinerMode = OUTLINERMODE_OUTLINEOBJECT;
1224 if ( !IsOutlText() )
1225 nOutlinerMode = OUTLINERMODE_TEXTOBJECT;
1226 rOutl.Init( nOutlinerMode );
1228 rOutl.SetGlobalCharStretching(100,100);
1229 EEControlBits nStat=rOutl.GetControlWord();
1230 nStat &= ~EEControlBits(EEControlBits::STRETCHING|EEControlBits::AUTOPAGESIZE);
1231 rOutl.SetControlWord(nStat);
1232 Size aNullSize;
1233 Size aMaxSize(100000,100000);
1234 rOutl.SetMinAutoPaperSize(aNullSize);
1235 rOutl.SetMaxAutoPaperSize(aMaxSize);
1236 rOutl.SetPaperSize(aMaxSize);
1237 rOutl.ClearPolygon();
1240 SdrOutliner& SdrTextObj::ImpGetDrawOutliner() const
1242 SdrOutliner& rOutl=pModel->GetDrawOutliner(this);
1244 // Code extracted to ImpInitDrawOutliner()
1245 ImpInitDrawOutliner( rOutl );
1247 return rOutl;
1250 // Extracted from Paint()
1251 void SdrTextObj::ImpSetupDrawOutlinerForPaint( bool bContourFrame,
1252 SdrOutliner& rOutliner,
1253 Rectangle& rTextRect,
1254 Rectangle& rAnchorRect,
1255 Rectangle& rPaintRect,
1256 Fraction& rFitXKorreg ) const
1258 if (!bContourFrame)
1260 // FitToSize can't be used together with ContourFrame for now
1261 if (IsFitToSize() || IsAutoFit())
1263 EEControlBits nStat=rOutliner.GetControlWord();
1264 nStat|=EEControlBits::STRETCHING|EEControlBits::AUTOPAGESIZE;
1265 rOutliner.SetControlWord(nStat);
1268 rOutliner.SetFixedCellHeight(static_cast<const SdrTextFixedCellHeightItem&>(GetMergedItem(SDRATTR_TEXT_USEFIXEDCELLHEIGHT)).GetValue());
1269 TakeTextRect(rOutliner, rTextRect, false, &rAnchorRect);
1270 rPaintRect = rTextRect;
1272 if (!bContourFrame)
1274 // FitToSize can't be used together with ContourFrame for now
1275 if (IsFitToSize())
1277 ImpSetCharStretching(rOutliner,rTextRect.GetSize(),rAnchorRect.GetSize(),rFitXKorreg);
1278 rPaintRect=rAnchorRect;
1280 else if (IsAutoFit())
1282 ImpAutoFitText(rOutliner);
1287 void SdrTextObj::ImpAutoFitText( SdrOutliner& rOutliner ) const
1289 const Size aShapeSize=GetSnapRect().GetSize();
1290 ImpAutoFitText( rOutliner,
1291 Size(aShapeSize.Width()-GetTextLeftDistance()-GetTextRightDistance(),
1292 aShapeSize.Height()-GetTextUpperDistance()-GetTextLowerDistance()),
1293 IsVerticalWriting() );
1296 void SdrTextObj::ImpAutoFitText( SdrOutliner& rOutliner, const Size& rTextSize, bool bIsVerticalWriting )
1298 // EditEngine formatting is unstable enough for
1299 // line-breaking text that we need some more samples
1301 // loop early-exits if we detect an already attained value
1302 sal_uInt16 nMinStretchX=0, nMinStretchY=0;
1303 sal_uInt16 aOldStretchXVals[]={0,0,0,0,0,0,0,0,0,0};
1304 const size_t aStretchArySize=SAL_N_ELEMENTS(aOldStretchXVals);
1305 for(unsigned int i=0; i<aStretchArySize; ++i)
1307 const Size aCurrTextSize = rOutliner.CalcTextSizeNTP();
1308 double fFactor(1.0);
1309 if( bIsVerticalWriting )
1310 fFactor = double(rTextSize.Width())/aCurrTextSize.Width();
1311 else
1312 fFactor = double(rTextSize.Height())/aCurrTextSize.Height();
1313 // fFactor scales in both x and y directions
1314 // - this is fine for bulleted words
1315 // - but it scales too much for a long paragraph
1316 // - taking sqrt scales long paragraphs the best
1317 // - bulleted words will have to go through more iterations
1318 fFactor = std::sqrt(fFactor);
1320 sal_uInt16 nCurrStretchX, nCurrStretchY;
1321 rOutliner.GetGlobalCharStretching(nCurrStretchX, nCurrStretchY);
1323 if (fFactor >= 1.0 )
1325 // resulting text area fits into available shape rect -
1326 // err on the larger stretching, to optimally fill area
1327 nMinStretchX = std::max(nMinStretchX,nCurrStretchX);
1328 nMinStretchY = std::max(nMinStretchY,nCurrStretchY);
1331 aOldStretchXVals[i] = nCurrStretchX;
1332 if( std::find(aOldStretchXVals, aOldStretchXVals+i, nCurrStretchX) != aOldStretchXVals+i )
1333 break; // same value already attained once; algo is looping, exit
1335 if (fFactor < 1.0 || (fFactor >= 1.0 && nCurrStretchX != 100))
1337 nCurrStretchX = sal::static_int_cast<sal_uInt16>(nCurrStretchX*fFactor);
1338 nCurrStretchY = sal::static_int_cast<sal_uInt16>(nCurrStretchY*fFactor);
1339 rOutliner.SetGlobalCharStretching(std::min(sal_uInt16(100),nCurrStretchX),
1340 std::min(sal_uInt16(100),nCurrStretchY));
1341 OSL_TRACE("SdrTextObj::onEditOutlinerStatusEvent(): zoom is %d", nCurrStretchX);
1345 OSL_TRACE("---- SdrTextObj::onEditOutlinerStatusEvent(): final zoom is %d ----", nMinStretchX);
1346 rOutliner.SetGlobalCharStretching(std::min(sal_uInt16(100),nMinStretchX),
1347 std::min(sal_uInt16(100),nMinStretchY));
1350 void SdrTextObj::SetupOutlinerFormatting( SdrOutliner& rOutl, Rectangle& rPaintRect ) const
1352 ImpInitDrawOutliner( rOutl );
1353 UpdateOutlinerFormatting( rOutl, rPaintRect );
1356 void SdrTextObj::UpdateOutlinerFormatting( SdrOutliner& rOutl, Rectangle& rPaintRect ) const
1358 Rectangle aTextRect;
1359 Rectangle aAnchorRect;
1360 Fraction aFitXKorreg(1,1);
1362 bool bContourFrame=IsContourTextFrame();
1364 if( GetModel() )
1366 MapMode aMapMode(GetModel()->GetScaleUnit(), Point(0,0),
1367 GetModel()->GetScaleFraction(),
1368 GetModel()->GetScaleFraction());
1369 rOutl.SetRefMapMode(aMapMode);
1372 ImpSetupDrawOutlinerForPaint( bContourFrame, rOutl, aTextRect, aAnchorRect, rPaintRect, aFitXKorreg );
1377 OutlinerParaObject* SdrTextObj::GetOutlinerParaObject() const
1379 SdrText* pText = getActiveText();
1380 if( pText )
1381 return pText->GetOutlinerParaObject();
1382 else
1383 return 0;
1386 void SdrTextObj::NbcSetOutlinerParaObject(OutlinerParaObject* pTextObject)
1388 NbcSetOutlinerParaObjectForText( pTextObject, getActiveText() );
1391 void SdrTextObj::NbcSetOutlinerParaObjectForText( OutlinerParaObject* pTextObject, SdrText* pText )
1393 if( pText )
1394 pText->SetOutlinerParaObject( pTextObject );
1396 if (pText && pText->GetOutlinerParaObject())
1398 SvxWritingModeItem aWritingMode(pText->GetOutlinerParaObject()->IsVertical()
1399 ? com::sun::star::text::WritingMode_TB_RL
1400 : com::sun::star::text::WritingMode_LR_TB,
1401 SDRATTR_TEXTDIRECTION);
1402 GetProperties().SetObjectItemDirect(aWritingMode);
1405 SetTextSizeDirty();
1406 if (IsTextFrame() && (IsAutoGrowHeight() || IsAutoGrowWidth()))
1407 { // adapt text frame!
1408 NbcAdjustTextFrameWidthAndHeight();
1410 if (!IsTextFrame())
1412 // the SnapRect keeps its size
1413 SetRectsDirty(true);
1416 // always invalidate BoundRect on change
1417 SetBoundRectDirty();
1418 ActionChanged();
1420 ImpSetTextStyleSheetListeners();
1421 ImpCheckMasterCachable();
1424 void SdrTextObj::NbcReformatText()
1426 SdrText* pText = getActiveText();
1427 if( pText && pText->GetOutlinerParaObject() )
1429 pText->ReformatText();
1430 if (bTextFrame)
1432 NbcAdjustTextFrameWidthAndHeight();
1434 else
1436 // the SnapRect keeps its size
1437 SetBoundRectDirty();
1438 SetRectsDirty(true);
1440 SetTextSizeDirty();
1441 ActionChanged();
1442 // i22396
1443 // Necessary here since we have no compare operator at the outliner
1444 // para object which may detect changes regarding the combination
1445 // of outliner para data and configuration (e.g., change of
1446 // formatting of text numerals)
1447 GetViewContact().flushViewObjectContacts(false);
1451 void SdrTextObj::ReformatText()
1453 if(GetOutlinerParaObject())
1455 Rectangle aBoundRect0;
1456 if (pUserCall!=NULL)
1457 aBoundRect0=GetLastBoundRect();
1459 NbcReformatText();
1460 SetChanged();
1461 BroadcastObjectChange();
1462 SendUserCall(SDRUSERCALL_RESIZE,aBoundRect0);
1466 SdrObjGeoData* SdrTextObj::NewGeoData() const
1468 return new SdrTextObjGeoData;
1471 void SdrTextObj::SaveGeoData(SdrObjGeoData& rGeo) const
1473 SdrAttrObj::SaveGeoData(rGeo);
1474 SdrTextObjGeoData& rTGeo=static_cast<SdrTextObjGeoData&>(rGeo);
1475 rTGeo.aRect = maRect;
1476 rTGeo.aGeo =aGeo;
1479 void SdrTextObj::RestGeoData(const SdrObjGeoData& rGeo)
1480 { // RectsDirty is called by SdrObject
1481 SdrAttrObj::RestGeoData(rGeo);
1482 const SdrTextObjGeoData& rTGeo=static_cast<const SdrTextObjGeoData&>(rGeo);
1483 NbcSetLogicRect(rTGeo.aRect);
1484 aGeo =rTGeo.aGeo;
1485 SetTextSizeDirty();
1488 SdrFitToSizeType SdrTextObj::GetFitToSize() const
1490 SdrFitToSizeType eType = SDRTEXTFIT_NONE;
1492 if(!IsAutoGrowWidth())
1493 eType = static_cast<const SdrTextFitToSizeTypeItem&>(GetObjectItem(SDRATTR_TEXT_FITTOSIZE)).GetValue();
1495 return eType;
1498 const Rectangle& SdrTextObj::GetGeoRect() const
1500 return maRect;
1503 void SdrTextObj::ForceOutlinerParaObject()
1505 SdrText* pText = getActiveText();
1506 if( pText && (pText->GetOutlinerParaObject() == 0) )
1508 sal_uInt16 nOutlMode = OUTLINERMODE_TEXTOBJECT;
1509 if( IsTextFrame() && eTextKind == OBJ_OUTLINETEXT )
1510 nOutlMode = OUTLINERMODE_OUTLINEOBJECT;
1512 pText->ForceOutlinerParaObject( nOutlMode );
1516 bool SdrTextObj::IsVerticalWriting() const
1518 if(pEdtOutl)
1520 return pEdtOutl->IsVertical();
1523 OutlinerParaObject* pOutlinerParaObject = GetOutlinerParaObject();
1524 if(pOutlinerParaObject)
1526 return pOutlinerParaObject->IsVertical();
1529 return false;
1532 void SdrTextObj::SetVerticalWriting(bool bVertical)
1534 OutlinerParaObject* pOutlinerParaObject = GetOutlinerParaObject();
1535 if( !pOutlinerParaObject && bVertical )
1537 // we only need to force a outliner para object if the default of
1538 // horizontal text is changed
1539 ForceOutlinerParaObject();
1540 pOutlinerParaObject = GetOutlinerParaObject();
1543 if( pOutlinerParaObject && (pOutlinerParaObject->IsVertical() != (bool)bVertical) )
1545 // get item settings
1546 const SfxItemSet& rSet = GetObjectItemSet();
1547 bool bAutoGrowWidth = static_cast<const SdrOnOffItem&>(rSet.Get(SDRATTR_TEXT_AUTOGROWWIDTH)).GetValue();
1548 bool bAutoGrowHeight = static_cast<const SdrOnOffItem&>(rSet.Get(SDRATTR_TEXT_AUTOGROWHEIGHT)).GetValue();
1550 // Also exchange hor/ver adjust items
1551 SdrTextHorzAdjust eHorz = static_cast<const SdrTextHorzAdjustItem&>(rSet.Get(SDRATTR_TEXT_HORZADJUST)).GetValue();
1552 SdrTextVertAdjust eVert = static_cast<const SdrTextVertAdjustItem&>(rSet.Get(SDRATTR_TEXT_VERTADJUST)).GetValue();
1554 // rescue object size
1555 Rectangle aObjectRect = GetSnapRect();
1557 // prepare ItemSet to set exchanged width and height items
1558 SfxItemSet aNewSet(*rSet.GetPool(),
1559 SDRATTR_TEXT_AUTOGROWHEIGHT, SDRATTR_TEXT_AUTOGROWHEIGHT,
1560 // Expanded item ranges to also support hor and ver adjust.
1561 SDRATTR_TEXT_VERTADJUST, SDRATTR_TEXT_VERTADJUST,
1562 SDRATTR_TEXT_AUTOGROWWIDTH, SDRATTR_TEXT_HORZADJUST,
1563 0, 0);
1565 aNewSet.Put(rSet);
1566 aNewSet.Put(makeSdrTextAutoGrowWidthItem(bAutoGrowHeight));
1567 aNewSet.Put(makeSdrTextAutoGrowHeightItem(bAutoGrowWidth));
1569 // Exchange horz and vert adjusts
1570 switch(eVert)
1572 case SDRTEXTVERTADJUST_TOP: aNewSet.Put(SdrTextHorzAdjustItem(SDRTEXTHORZADJUST_RIGHT)); break;
1573 case SDRTEXTVERTADJUST_CENTER: aNewSet.Put(SdrTextHorzAdjustItem(SDRTEXTHORZADJUST_CENTER)); break;
1574 case SDRTEXTVERTADJUST_BOTTOM: aNewSet.Put(SdrTextHorzAdjustItem(SDRTEXTHORZADJUST_LEFT)); break;
1575 case SDRTEXTVERTADJUST_BLOCK: aNewSet.Put(SdrTextHorzAdjustItem(SDRTEXTHORZADJUST_BLOCK)); break;
1577 switch(eHorz)
1579 case SDRTEXTHORZADJUST_LEFT: aNewSet.Put(SdrTextVertAdjustItem(SDRTEXTVERTADJUST_BOTTOM)); break;
1580 case SDRTEXTHORZADJUST_CENTER: aNewSet.Put(SdrTextVertAdjustItem(SDRTEXTVERTADJUST_CENTER)); break;
1581 case SDRTEXTHORZADJUST_RIGHT: aNewSet.Put(SdrTextVertAdjustItem(SDRTEXTVERTADJUST_TOP)); break;
1582 case SDRTEXTHORZADJUST_BLOCK: aNewSet.Put(SdrTextVertAdjustItem(SDRTEXTVERTADJUST_BLOCK)); break;
1585 SetObjectItemSet(aNewSet);
1587 pOutlinerParaObject = GetOutlinerParaObject();
1588 if( pOutlinerParaObject )
1590 // set ParaObject orientation accordingly
1591 pOutlinerParaObject->SetVertical(bVertical);
1594 // restore object size
1595 SetSnapRect(aObjectRect);
1601 // transformation interface for StarOfficeAPI. This implements support for
1602 // homogeneous 3x3 matrices containing the transformation of the SdrObject. At the
1603 // moment it contains a shearX, rotation and translation, but for setting all linear
1604 // transforms like Scale, ShearX, ShearY, Rotate and Translate are supported.
1607 // gets base transformation and rectangle of object. If it's an SdrPathObj it fills the PolyPolygon
1608 // with the base geometry and returns TRUE. Otherwise it returns FALSE.
1609 bool SdrTextObj::TRGetBaseGeometry(basegfx::B2DHomMatrix& rMatrix, basegfx::B2DPolyPolygon& /*rPolyPolygon*/) const
1611 // get turn and shear
1612 double fRotate = (aGeo.nRotationAngle / 100.0) * F_PI180;
1613 double fShearX = (aGeo.nShearAngle / 100.0) * F_PI180;
1615 // get aRect, this is the unrotated snaprect
1616 Rectangle aRectangle(maRect);
1618 // fill other values
1619 basegfx::B2DTuple aScale(aRectangle.GetWidth(), aRectangle.GetHeight());
1620 basegfx::B2DTuple aTranslate(aRectangle.Left(), aRectangle.Top());
1622 // position maybe relative to anchorpos, convert
1623 if( pModel && pModel->IsWriter() )
1625 if(GetAnchorPos().X() || GetAnchorPos().Y())
1627 aTranslate -= basegfx::B2DTuple(GetAnchorPos().X(), GetAnchorPos().Y());
1631 // force MapUnit to 100th mm
1632 const SfxMapUnit eMapUnit(GetObjectMapUnit());
1633 if(eMapUnit != SFX_MAPUNIT_100TH_MM)
1635 switch(eMapUnit)
1637 case SFX_MAPUNIT_TWIP :
1639 // position
1640 aTranslate.setX(ImplTwipsToMM(aTranslate.getX()));
1641 aTranslate.setY(ImplTwipsToMM(aTranslate.getY()));
1643 // size
1644 aScale.setX(ImplTwipsToMM(aScale.getX()));
1645 aScale.setY(ImplTwipsToMM(aScale.getY()));
1647 break;
1649 default:
1651 OSL_FAIL("TRGetBaseGeometry: Missing unit translation to 100th mm!");
1656 // build matrix
1657 rMatrix = basegfx::tools::createScaleShearXRotateTranslateB2DHomMatrix(
1658 aScale,
1659 basegfx::fTools::equalZero(fShearX) ? 0.0 : tan(fShearX),
1660 basegfx::fTools::equalZero(fRotate) ? 0.0 : -fRotate,
1661 aTranslate);
1663 return false;
1666 // sets the base geometry of the object using infos contained in the homogeneous 3x3 matrix.
1667 // If it's an SdrPathObj it will use the provided geometry information. The Polygon has
1668 // to use (0,0) as upper left and will be scaled to the given size in the matrix.
1669 void SdrTextObj::TRSetBaseGeometry(const basegfx::B2DHomMatrix& rMatrix, const basegfx::B2DPolyPolygon& /*rPolyPolygon*/)
1671 // break up matrix
1672 basegfx::B2DTuple aScale;
1673 basegfx::B2DTuple aTranslate;
1674 double fRotate(0.0);
1675 double fShearX(0.0);
1676 rMatrix.decompose(aScale, aTranslate, fRotate, fShearX);
1678 // #i75086# Old DrawingLayer (GeoStat and geometry) does not support holding negative scalings
1679 // in X and Y which equal a 180 degree rotation. Recognize it and react accordingly
1680 if(basegfx::fTools::less(aScale.getX(), 0.0) && basegfx::fTools::less(aScale.getY(), 0.0))
1682 aScale.setX(fabs(aScale.getX()));
1683 aScale.setY(fabs(aScale.getY()));
1684 fRotate = fmod(fRotate + F_PI, F_2PI);
1687 // reset object shear and rotations
1688 aGeo.nRotationAngle = 0;
1689 aGeo.RecalcSinCos();
1690 aGeo.nShearAngle = 0;
1691 aGeo.RecalcTan();
1693 // force metric to pool metric
1694 const SfxMapUnit eMapUnit(GetObjectMapUnit());
1695 if(eMapUnit != SFX_MAPUNIT_100TH_MM)
1697 switch(eMapUnit)
1699 case SFX_MAPUNIT_TWIP :
1701 // position
1702 aTranslate.setX(ImplMMToTwips(aTranslate.getX()));
1703 aTranslate.setY(ImplMMToTwips(aTranslate.getY()));
1705 // size
1706 aScale.setX(ImplMMToTwips(aScale.getX()));
1707 aScale.setY(ImplMMToTwips(aScale.getY()));
1709 break;
1711 default:
1713 OSL_FAIL("TRSetBaseGeometry: Missing unit translation to PoolMetric!");
1718 // if anchor is used, make position relative to it
1719 if( pModel && pModel->IsWriter() )
1721 if(GetAnchorPos().X() || GetAnchorPos().Y())
1723 aTranslate += basegfx::B2DTuple(GetAnchorPos().X(), GetAnchorPos().Y());
1727 // build and set BaseRect (use scale)
1728 Point aPoint = Point();
1729 Size aSize(FRound(aScale.getX()), FRound(aScale.getY()));
1730 Rectangle aBaseRect(aPoint, aSize);
1731 SetSnapRect(aBaseRect);
1733 // shear?
1734 if(!basegfx::fTools::equalZero(fShearX))
1736 GeoStat aGeoStat;
1737 aGeoStat.nShearAngle = FRound((atan(fShearX) / F_PI180) * 100.0);
1738 aGeoStat.RecalcTan();
1739 Shear(Point(), aGeoStat.nShearAngle, aGeoStat.nTan, false);
1742 // rotation?
1743 if(!basegfx::fTools::equalZero(fRotate))
1745 GeoStat aGeoStat;
1747 // #i78696#
1748 // fRotate is matematically correct, but aGeoStat.nRotationAngle is
1749 // mirrored -> mirror value here
1750 aGeoStat.nRotationAngle = NormAngle360(FRound(-fRotate / F_PI18000));
1751 aGeoStat.RecalcSinCos();
1752 Rotate(Point(), aGeoStat.nRotationAngle, aGeoStat.nSin, aGeoStat.nCos);
1755 // translate?
1756 if(!aTranslate.equalZero())
1758 Move(Size(FRound(aTranslate.getX()), FRound(aTranslate.getY())));
1762 bool SdrTextObj::IsReallyEdited() const
1764 return pEdtOutl && pEdtOutl->IsModified();
1767 // moved inlines here form hxx
1769 long SdrTextObj::GetEckenradius() const
1771 return static_cast<const SdrMetricItem&>(GetObjectItemSet().Get(SDRATTR_ECKENRADIUS)).GetValue();
1774 long SdrTextObj::GetMinTextFrameHeight() const
1776 return static_cast<const SdrMetricItem&>(GetObjectItemSet().Get(SDRATTR_TEXT_MINFRAMEHEIGHT)).GetValue();
1779 long SdrTextObj::GetMaxTextFrameHeight() const
1781 return static_cast<const SdrMetricItem&>(GetObjectItemSet().Get(SDRATTR_TEXT_MAXFRAMEHEIGHT)).GetValue();
1784 long SdrTextObj::GetMinTextFrameWidth() const
1786 return static_cast<const SdrMetricItem&>(GetObjectItemSet().Get(SDRATTR_TEXT_MINFRAMEWIDTH)).GetValue();
1789 long SdrTextObj::GetMaxTextFrameWidth() const
1791 return static_cast<const SdrMetricItem&>(GetObjectItemSet().Get(SDRATTR_TEXT_MAXFRAMEWIDTH)).GetValue();
1794 bool SdrTextObj::IsFontwork() const
1796 return !bTextFrame // Default is FALSE
1797 && static_cast<const XFormTextStyleItem&>(GetObjectItemSet().Get(XATTR_FORMTXTSTYLE)).GetValue() != XFT_NONE;
1800 bool SdrTextObj::IsHideContour() const
1802 return !bTextFrame // Default is: no, don't HideContour; HideContour not together with TextFrames
1803 && static_cast<const XFormTextHideFormItem&>(GetObjectItemSet().Get(XATTR_FORMTXTHIDEFORM)).GetValue();
1806 bool SdrTextObj::IsContourTextFrame() const
1808 return !bTextFrame // ContourFrame not together with normal TextFrames
1809 && static_cast<const SdrOnOffItem&>(GetObjectItemSet().Get(SDRATTR_TEXT_CONTOURFRAME)).GetValue();
1812 long SdrTextObj::GetTextLeftDistance() const
1814 return static_cast<const SdrMetricItem&>(GetObjectItemSet().Get(SDRATTR_TEXT_LEFTDIST)).GetValue();
1817 long SdrTextObj::GetTextRightDistance() const
1819 return static_cast<const SdrMetricItem&>(GetObjectItemSet().Get(SDRATTR_TEXT_RIGHTDIST)).GetValue();
1822 long SdrTextObj::GetTextUpperDistance() const
1824 return static_cast<const SdrMetricItem&>(GetObjectItemSet().Get(SDRATTR_TEXT_UPPERDIST)).GetValue();
1827 long SdrTextObj::GetTextLowerDistance() const
1829 return static_cast<const SdrMetricItem&>(GetObjectItemSet().Get(SDRATTR_TEXT_LOWERDIST)).GetValue();
1832 SdrTextAniKind SdrTextObj::GetTextAniKind() const
1834 return static_cast<const SdrTextAniKindItem&>(GetObjectItemSet().Get(SDRATTR_TEXT_ANIKIND)).GetValue();
1837 SdrTextAniDirection SdrTextObj::GetTextAniDirection() const
1839 return static_cast<const SdrTextAniDirectionItem&>(GetObjectItemSet().Get(SDRATTR_TEXT_ANIDIRECTION)).GetValue();
1842 // Get necessary data for text scroll animation. ATM base it on a Text-Metafile and a
1843 // painting rectangle. Rotation is excluded from the returned values.
1844 GDIMetaFile* SdrTextObj::GetTextScrollMetaFileAndRectangle(
1845 Rectangle& rScrollRectangle, Rectangle& rPaintRectangle)
1847 GDIMetaFile* pRetval = 0L;
1848 SdrOutliner& rOutliner = ImpGetDrawOutliner();
1849 Rectangle aTextRect;
1850 Rectangle aAnchorRect;
1851 Rectangle aPaintRect;
1852 Fraction aFitXKorreg(1,1);
1853 bool bContourFrame(IsContourTextFrame());
1855 // get outliner set up. To avoid getting a somehow rotated MetaFile,
1856 // temporarily disable object rotation.
1857 sal_Int32 nAngle(aGeo.nRotationAngle);
1858 aGeo.nRotationAngle = 0L;
1859 ImpSetupDrawOutlinerForPaint( bContourFrame, rOutliner, aTextRect, aAnchorRect, aPaintRect, aFitXKorreg );
1860 aGeo.nRotationAngle = nAngle;
1862 Rectangle aScrollFrameRect(aPaintRect);
1863 const SfxItemSet& rSet = GetObjectItemSet();
1864 SdrTextAniDirection eDirection = static_cast<const SdrTextAniDirectionItem&>(rSet.Get(SDRATTR_TEXT_ANIDIRECTION)).GetValue();
1866 if(SDRTEXTANI_LEFT == eDirection || SDRTEXTANI_RIGHT == eDirection)
1868 aScrollFrameRect.Left() = aAnchorRect.Left();
1869 aScrollFrameRect.Right() = aAnchorRect.Right();
1872 if(SDRTEXTANI_UP == eDirection || SDRTEXTANI_DOWN == eDirection)
1874 aScrollFrameRect.Top() = aAnchorRect.Top();
1875 aScrollFrameRect.Bottom() = aAnchorRect.Bottom();
1878 // create the MetaFile
1879 pRetval = new GDIMetaFile;
1880 ScopedVclPtrInstance< VirtualDevice > pBlackHole;
1881 pBlackHole->EnableOutput(false);
1882 pRetval->Record(pBlackHole);
1883 Point aPaintPos = aPaintRect.TopLeft();
1885 rOutliner.Draw(pBlackHole, aPaintPos);
1887 pRetval->Stop();
1888 pRetval->WindStart();
1890 // return PaintRectanglePixel and pRetval;
1891 rScrollRectangle = aScrollFrameRect;
1892 rPaintRectangle = aPaintRect;
1894 return pRetval;
1897 // Access to TextAnimationAllowed flag
1898 bool SdrTextObj::IsAutoFit() const
1900 return GetFitToSize()==SDRTEXTFIT_AUTOFIT;
1903 bool SdrTextObj::IsFitToSize() const
1905 const SdrFitToSizeType eFit=GetFitToSize();
1906 return (eFit==SDRTEXTFIT_PROPORTIONAL || eFit==SDRTEXTFIT_ALLLINES);
1909 void SdrTextObj::SetTextAnimationAllowed(bool bNew)
1911 if(mbTextAnimationAllowed != bNew)
1913 mbTextAnimationAllowed = bNew;
1914 ActionChanged();
1918 /** called from the SdrObjEditView during text edit when the status of the edit outliner changes */
1919 void SdrTextObj::onEditOutlinerStatusEvent( EditStatus* pEditStatus )
1921 const EditStatusFlags nStat = pEditStatus->GetStatusWord();
1922 const bool bGrowX = bool(nStat & EditStatusFlags::TEXTWIDTHCHANGED);
1923 const bool bGrowY = bool(nStat & EditStatusFlags::TEXTHEIGHTCHANGED);
1924 if(bTextFrame && (bGrowX || bGrowY))
1926 if ((bGrowX && IsAutoGrowWidth()) || (bGrowY && IsAutoGrowHeight()))
1928 AdjustTextFrameWidthAndHeight();
1930 else if (IsAutoFit() && !mbInDownScale)
1932 assert(pEdtOutl);
1933 mbInDownScale = true;
1935 // sucks that we cannot disable paints via
1936 // pEdtOutl->SetUpdateMode(FALSE) - but EditEngine skips
1937 // formatting as well, then.
1938 ImpAutoFitText(*pEdtOutl);
1939 mbInDownScale = false;
1944 /** returns the currently active text. */
1945 SdrText* SdrTextObj::getActiveText() const
1947 if( !mpText )
1948 return getText( 0 );
1949 else
1950 return mpText;
1953 /** returns the nth available text. */
1954 SdrText* SdrTextObj::getText( sal_Int32 nIndex ) const
1956 if( nIndex == 0 )
1958 if( mpText == 0 )
1959 const_cast< SdrTextObj* >(this)->mpText = new SdrText( *(const_cast< SdrTextObj* >(this)) );
1960 return mpText;
1962 else
1964 return 0;
1968 /** returns the number of texts available for this object. */
1969 sal_Int32 SdrTextObj::getTextCount() const
1971 return 1;
1974 /** changes the current active text */
1975 void SdrTextObj::setActiveText( sal_Int32 /*nIndex*/ )
1979 /** returns the index of the text that contains the given point or -1 */
1980 sal_Int32 SdrTextObj::CheckTextHit(const Point& /*rPnt*/) const
1982 return 0;
1985 void SdrTextObj::SetObjectItemNoBroadcast(const SfxPoolItem& rItem)
1987 static_cast< sdr::properties::TextProperties& >(GetProperties()).SetObjectItemNoBroadcast(rItem);
1992 // The concept of the text object:
1993 // ~~~~~~~~~~~~~~~~~~~~~~~~
1994 // Attributes/Variations:
1995 // - bool text frame / graphics object with caption
1996 // - bool FontWork (if it is not a text frame and not a ContourTextFrame)
1997 // - bool ContourTextFrame (if it is not a text frame and not Fontwork)
1998 // - long rotation angle (if it is not FontWork)
1999 // - long text frame margins (if it is not FontWork)
2000 // - bool FitToSize (if it is not FontWork)
2001 // - bool AutoGrowingWidth/Height (if it is not FitToSize and not FontWork)
2002 // - long Min/MaxFrameWidth/Height (if AutoGrowingWidth/Height)
2003 // - enum horizontal text anchoring left,center,right,justify/block,Stretch(ni)
2004 // - enum vertical text anchoring top, middle, bottom, block, stretch(ni)
2005 // - enum ticker text (if it is not FontWork)
2007 // Every derived object is either a text frame (bTextFrame=true)
2008 // or a drawing object with a caption (bTextFrame=false).
2010 // Default anchoring for text frames:
2011 // SDRTEXTHORZADJUST_BLOCK, SDRTEXTVERTADJUST_TOP
2012 // = static Pool defaults
2013 // Default anchoring for drawing objects with a caption:
2014 // SDRTEXTHORZADJUST_CENTER, SDRTEXTVERTADJUST_CENTER
2015 // via "hard" attribution of SdrAttrObj
2017 // Every object derived from SdrTextObj must return an "UnrotatedSnapRect"
2018 // (->TakeUnrotatedSnapRect()) (the reference point for the rotation is the top
2019 // left of the rectangle (aGeo.nRotationAngle)) which is the basis for anchoring
2020 // text. We then subtract the text frame margins from this rectangle, as a re-
2021 // sult we get the anchoring area (->TakeTextAnchorRect()). Within this area, we
2022 // calculate the anchoring point and the painting area, depending on the hori-
2023 // zontal and vertical adjustment of the text (SdrTextVertAdjust,
2024 // SdrTextHorzAdjust).
2025 // In the case of drawing objects with a caption the painting area might well
2026 // be larger than the anchoring area, for text frames on the other hand, it is
2027 // always of the same or a smaller size (except when there are negative text
2028 // frame margins).
2030 // FitToSize takes priority over text anchoring and AutoGrowHeight/Width. When
2031 // FitToSize is turned on, the painting area is always equal to the anchoring
2032 // area. Additionally, FitToSize doesn't allow automatic line breaks.
2034 // ContourTextFrame:
2035 // - long rotation angle
2036 // - long text frame margins (maybe later)
2037 // - bool FitToSize (maybe later)
2038 // - bool AutoGrowingWidth/Height (maybe much later)
2039 // - long Min/MaxFrameWidth/Height (maybe much later)
2040 // - enum horizontal text anchoring (maybe later, for now: left, centered)
2041 // - enum vertical text anchoring (maybe later, for now: top)
2042 // - enum ticker text (maybe later, maybe even with correct clipping)
2044 // When making changes, check these:
2045 // - Paint
2046 // - HitTest
2047 // - ConvertToPoly
2048 // - Edit
2049 // - Printing, Saving, Painting in neighboring View while editing
2050 // - ModelChanged (e. g. through a neighboring View or rulers) while editing
2051 // - FillColorChanged while editin
2052 // - and many more...
2056 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */