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 .
20 #include <basegfx/matrix/b2dhommatrix.hxx>
21 #include <basegfx/polygon/b2dpolygon.hxx>
22 #include <basegfx/polygon/b2dpolygontools.hxx>
23 #include <basegfx/range/b2drange.hxx>
24 #include <basegfx/tuple/b2dtuple.hxx>
25 #include <editeng/eeitem.hxx>
26 #include <svl/style.hxx>
27 #include <tools/bigint.hxx>
28 #include <tools/helpers.hxx>
30 #include "svdconv.hxx"
31 #include "svdglob.hxx"
32 #include "svx/svdstr.hrc"
34 #include <sdr/contact/viewcontactofsdrcaptionobj.hxx>
35 #include <sdr/properties/captionproperties.hxx>
36 #include <svx/sdrhittesthelper.hxx>
37 #include <svx/svddrag.hxx>
38 #include <svx/svdetc.hxx>
39 #include <svx/svdhdl.hxx>
40 #include <svx/svdmodel.hxx>
41 #include <svx/svdocapt.hxx>
42 #include <svx/svdogrp.hxx>
43 #include <svx/svdpage.hxx>
44 #include <svx/svdpool.hxx>
45 #include <svx/svdtrans.hxx>
46 #include <svx/svdview.hxx>
47 #include <svx/sxcaitm.hxx>
48 #include <svx/sxcecitm.hxx>
49 #include <svx/sxcgitm.hxx>
50 #include <svx/sxcllitm.hxx>
51 #include <svx/sxctitm.hxx>
52 #include <svx/xflclit.hxx>
53 #include <svx/xflhtit.hxx>
54 #include <svx/xfltrit.hxx>
55 #include <svx/xlnwtit.hxx>
56 #include <svx/xpoly.hxx>
57 #include <svx/xpool.hxx>
61 enum EscDir
{LKS
,RTS
,OBN
,UNT
};
72 SdrCaptionEscDir eEscDir
;
84 eEscDir
=SDRCAPT_ESCHORIZONTAL
;
91 void CalcEscPos(const Point
& rTail
, const Rectangle
& rRect
, Point
& rPt
, EscDir
& rDir
) const;
94 void ImpCaptParams::CalcEscPos(const Point
& rTailPt
, const Rectangle
& rRect
, Point
& rPt
, EscDir
& rDir
) const
96 Point
aTl(rTailPt
); // copy locally for performance reasons
99 nX
=rRect
.Right()-rRect
.Left();
100 nX
=BigMulDiv(nX
,nEscRel
,10000);
101 nY
=rRect
.Bottom()-rRect
.Top();
102 nY
=BigMulDiv(nY
,nEscRel
,10000);
111 bool bTryH
=eEscDir
==SDRCAPT_ESCBESTFIT
;
113 if (eType
!=SDRCAPT_TYPE1
) {
114 bTryH
=eEscDir
==SDRCAPT_ESCHORIZONTAL
;
116 bTryH
=eEscDir
==SDRCAPT_ESCVERTICAL
;
119 bool bTryV
=eEscDir
==SDRCAPT_ESCBESTFIT
;
121 if (eType
!=SDRCAPT_TYPE1
) {
122 bTryV
=eEscDir
==SDRCAPT_ESCVERTICAL
;
124 bTryV
=eEscDir
==SDRCAPT_ESCHORIZONTAL
;
129 Point
aLft(rRect
.Left()-nGap
,nY
);
130 Point
aRgt(rRect
.Right()+nGap
,nY
);
131 bool bLft
=(aTl
.X()-aLft
.X()<aRgt
.X()-aTl
.X());
141 Point
aTop(nX
,rRect
.Top()-nGap
);
142 Point
aBtm(nX
,rRect
.Bottom()+nGap
);
143 bool bTop
=(aTl
.Y()-aTop
.Y()<aBtm
.Y()-aTl
.Y());
153 bool bTakeIt
=eEscDir
!=SDRCAPT_ESCBESTFIT
;
155 BigInt
aHorX(aBestPt
.X()-aTl
.X()); aHorX
*=aHorX
;
156 BigInt
aHorY(aBestPt
.Y()-aTl
.Y()); aHorY
*=aHorY
;
157 BigInt
aVerX(aBest2
.X()-aTl
.X()); aVerX
*=aVerX
;
158 BigInt
aVerY(aBest2
.Y()-aTl
.Y()); aVerY
*=aVerY
;
159 if (eType
!=SDRCAPT_TYPE1
) {
160 bTakeIt
=aVerX
+aVerY
<aHorX
+aHorY
;
162 bTakeIt
=aVerX
+aVerY
>=aHorX
+aHorY
;
175 // BaseProperties section
177 sdr::properties::BaseProperties
* SdrCaptionObj::CreateObjectSpecificProperties()
179 return new sdr::properties::CaptionProperties(*this);
183 // DrawContact section
185 sdr::contact::ViewContact
* SdrCaptionObj::CreateObjectSpecificViewContact()
187 return new sdr::contact::ViewContactOfSdrCaptionObj(*this);
192 TYPEINIT1(SdrCaptionObj
,SdrRectObj
);
194 SdrCaptionObj::SdrCaptionObj():
195 SdrRectObj(OBJ_TEXT
),
196 aTailPoly(3), // default size: 3 points = 2 lines
197 mbSpecialTextBoxShadow(false),
202 SdrCaptionObj::SdrCaptionObj(const Rectangle
& rRect
, const Point
& rTail
):
203 SdrRectObj(OBJ_TEXT
,rRect
),
204 aTailPoly(3), // default size: 3 points = 2 lines
205 mbSpecialTextBoxShadow(false),
208 aTailPoly
[0]=maFixedTailPos
=rTail
;
211 SdrCaptionObj::~SdrCaptionObj()
215 void SdrCaptionObj::TakeObjInfo(SdrObjTransformInfoRec
& rInfo
) const
217 rInfo
.bRotateFreeAllowed
=false;
218 rInfo
.bRotate90Allowed
=false;
219 rInfo
.bMirrorFreeAllowed
=false;
220 rInfo
.bMirror45Allowed
=false;
221 rInfo
.bMirror90Allowed
=false;
222 rInfo
.bTransparenceAllowed
= false;
223 rInfo
.bGradientAllowed
= false;
224 rInfo
.bShearAllowed
=false;
225 rInfo
.bEdgeRadiusAllowed
=false;
226 rInfo
.bCanConvToPath
=true;
227 rInfo
.bCanConvToPoly
=true;
228 rInfo
.bCanConvToPathLineToArea
=false;
229 rInfo
.bCanConvToPolyLineToArea
=false;
230 rInfo
.bCanConvToContour
= (rInfo
.bCanConvToPoly
|| LineGeometryUsageIsNecessary());
233 sal_uInt16
SdrCaptionObj::GetObjIdentifier() const
235 return sal_uInt16(OBJ_CAPTION
);
238 SdrCaptionObj
* SdrCaptionObj::Clone() const
240 return CloneHelper
< SdrCaptionObj
>();
243 OUString
SdrCaptionObj::TakeObjNameSingul() const
245 OUStringBuffer
sName(ImpGetResStr(STR_ObjNameSingulCAPTION
));
247 OUString
aName(GetName());
248 if (!aName
.isEmpty())
256 return sName
.makeStringAndClear();
259 OUString
SdrCaptionObj::TakeObjNamePlural() const
261 return ImpGetResStr(STR_ObjNamePluralCAPTION
);
264 basegfx::B2DPolyPolygon
SdrCaptionObj::TakeXorPoly() const
266 basegfx::B2DPolyPolygon
aPolyPoly(SdrRectObj::TakeXorPoly());
267 aPolyPoly
.append(aTailPoly
.getB2DPolygon());
272 sal_uInt32
SdrCaptionObj::GetHdlCount() const
274 sal_uInt32
nCount1(SdrRectObj::GetHdlCount());
275 // Currently only dragging the tail's end is implemented.
279 SdrHdl
* SdrCaptionObj::GetHdl(sal_uInt32 nHdlNum
) const
281 const sal_uInt32
nRectHdlAnz(SdrRectObj::GetHdlCount());
283 if(nHdlNum
< nRectHdlAnz
)
285 return SdrRectObj::GetHdl(nHdlNum
);
289 sal_uInt32
nPntNum(nHdlNum
);
290 nPntNum
-= nRectHdlAnz
;
292 if(nPntNum
< aTailPoly
.GetSize())
294 SdrHdl
* pHdl
= new SdrHdl(aTailPoly
.GetPoint((sal_uInt16
)nPntNum
), HDL_POLY
);
295 pHdl
->SetPolyNum(1L);
296 pHdl
->SetPointNum(nPntNum
);
308 bool SdrCaptionObj::hasSpecialDrag() const
313 bool SdrCaptionObj::beginSpecialDrag(SdrDragStat
& rDrag
) const
315 const SdrHdl
* pHdl
= rDrag
.GetHdl();
316 rDrag
.SetEndDragChangesAttributes(true);
317 rDrag
.SetEndDragChangesGeoAndAttributes(true);
319 if(pHdl
&& 0 == pHdl
->GetPolyNum())
321 return SdrRectObj::beginSpecialDrag(rDrag
);
325 rDrag
.SetOrtho8Possible(true);
332 rDrag
.SetNoSnap(true);
333 rDrag
.SetActionRect(maRect
);
335 Point
aHit(rDrag
.GetStart());
337 if(rDrag
.GetPageView() && SdrObjectPrimitiveHit(*this, aHit
, 0, *rDrag
.GetPageView(), 0, false))
344 if((1 == pHdl
->GetPolyNum()) && (0 == pHdl
->GetPointNum()))
352 bool SdrCaptionObj::applySpecialDrag(SdrDragStat
& rDrag
)
354 const SdrHdl
* pHdl
= rDrag
.GetHdl();
356 if(pHdl
&& 0 == pHdl
->GetPolyNum())
358 const bool bRet(SdrRectObj::applySpecialDrag(rDrag
));
366 Point
aDelt(rDrag
.GetNow()-rDrag
.GetStart());
370 maRect
.Move(aDelt
.X(),aDelt
.Y());
374 aTailPoly
[0] += aDelt
;
384 OUString
SdrCaptionObj::getSpecialDragComment(const SdrDragStat
& rDrag
) const
386 const bool bCreateComment(rDrag
.GetView() && this == rDrag
.GetView()->GetCreateObj());
394 const SdrHdl
* pHdl
= rDrag
.GetHdl();
396 if(pHdl
&& 0 == pHdl
->GetPolyNum())
398 return SdrRectObj::getSpecialDragComment(rDrag
);
406 ImpTakeDescriptionStr(STR_DragCaptFram
, aStr
);
410 ImpTakeDescriptionStr(STR_DragCaptTail
, aStr
);
420 void SdrCaptionObj::ImpGetCaptParams(ImpCaptParams
& rPara
) const
422 const SfxItemSet
& rSet
= GetObjectItemSet();
423 rPara
.eType
=static_cast<const SdrCaptionTypeItem
&> (rSet
.Get(SDRATTR_CAPTIONTYPE
)).GetValue();
424 rPara
.bFixedAngle
=static_cast<const SdrOnOffItem
&> (rSet
.Get(SDRATTR_CAPTIONFIXEDANGLE
)).GetValue();
425 rPara
.nAngle
=static_cast<const SdrCaptionAngleItem
&> (rSet
.Get(SDRATTR_CAPTIONANGLE
)).GetValue();
426 rPara
.nGap
=static_cast<const SdrCaptionGapItem
&> (rSet
.Get(SDRATTR_CAPTIONGAP
)).GetValue();
427 rPara
.eEscDir
=static_cast<const SdrCaptionEscDirItem
&> (rSet
.Get(SDRATTR_CAPTIONESCDIR
)).GetValue();
428 rPara
.bEscRel
=static_cast<const SdrCaptionEscIsRelItem
&> (rSet
.Get(SDRATTR_CAPTIONESCISREL
)).GetValue();
429 rPara
.nEscRel
=static_cast<const SdrCaptionEscRelItem
&> (rSet
.Get(SDRATTR_CAPTIONESCREL
)).GetValue();
430 rPara
.nEscAbs
=static_cast<const SdrCaptionEscAbsItem
&> (rSet
.Get(SDRATTR_CAPTIONESCABS
)).GetValue();
431 rPara
.nLineLen
=static_cast<const SdrCaptionLineLenItem
&> (rSet
.Get(SDRATTR_CAPTIONLINELEN
)).GetValue();
432 rPara
.bFitLineLen
=static_cast<const SdrCaptionFitLineLenItem
&>(rSet
.Get(SDRATTR_CAPTIONFITLINELEN
)).GetValue();
435 void SdrCaptionObj::ImpRecalcTail()
438 ImpGetCaptParams(aPara
);
439 ImpCalcTail(aPara
, aTailPoly
, maRect
);
445 // SdrCaptionObj::ImpCalcTail1 does move the object(!). What a hack.
446 // I really wonder why this had not triggered problems before. I am
447 // sure there are some places where SetTailPos() is called at least
448 // twice or SetSnapRect after it again just to work around this.
449 // Changed this method to not do that.
450 // Also found why this has been done: For interactive dragging of the
451 // tail end pos for SDRCAPT_TYPE1. This sure was the simplest method
452 // to achieve this, at the cost of making a whole group of const methods
453 // of this object implicitly change the object's position.
454 void SdrCaptionObj::ImpCalcTail1(const ImpCaptParams
& rPara
, Polygon
& rPoly
, Rectangle
& rRect
) const
465 rPara
.CalcEscPos(aTl
, rRect
, aEscPos
, eEscDir
);
468 if(eEscDir
==LKS
|| eEscDir
==RTS
)
470 aPol
[0].X() = aEscPos
.X();
474 aPol
[0].Y() = aEscPos
.Y();
480 void SdrCaptionObj::ImpCalcTail2(const ImpCaptParams
& rPara
, Polygon
& rPoly
, Rectangle
& rRect
) const
481 { // Gap/EscDir/EscPos/Angle
488 rPara
.CalcEscPos(aTl
,rRect
,aEscPos
,eEscDir
);
491 if (!rPara
.bFixedAngle
) {
492 // TODO: Implementation missing.
497 void SdrCaptionObj::ImpCalcTail3(const ImpCaptParams
& rPara
, Polygon
& rPoly
, Rectangle
& rRect
) const
498 { // Gap/EscDir/EscPos/Angle/LineLen
505 rPara
.CalcEscPos(aTl
,rRect
,aEscPos
,eEscDir
);
509 if (eEscDir
==LKS
|| eEscDir
==RTS
) {
510 if (rPara
.bFitLineLen
) {
511 aPol
[1].X()=(aTl
.X()+aEscPos
.X())/2;
513 if (eEscDir
==LKS
) aPol
[1].X()-=rPara
.nLineLen
;
514 else aPol
[1].X()+=rPara
.nLineLen
;
517 if (rPara
.bFitLineLen
) {
518 aPol
[1].Y()=(aTl
.Y()+aEscPos
.Y())/2;
520 if (eEscDir
==OBN
) aPol
[1].Y()-=rPara
.nLineLen
;
521 else aPol
[1].Y()+=rPara
.nLineLen
;
524 if (!rPara
.bFixedAngle
) {
525 // TODO: Implementation missing.
530 void SdrCaptionObj::ImpCalcTail4(const ImpCaptParams
& rPara
, Polygon
& rPoly
, Rectangle
& rRect
) const
532 ImpCalcTail3(rPara
,rPoly
,rRect
);
535 void SdrCaptionObj::ImpCalcTail(const ImpCaptParams
& rPara
, Polygon
& rPoly
, Rectangle
& rRect
) const
537 switch (rPara
.eType
) {
538 case SDRCAPT_TYPE1
: ImpCalcTail1(rPara
,rPoly
,rRect
); break;
539 case SDRCAPT_TYPE2
: ImpCalcTail2(rPara
,rPoly
,rRect
); break;
540 case SDRCAPT_TYPE3
: ImpCalcTail3(rPara
,rPoly
,rRect
); break;
541 case SDRCAPT_TYPE4
: ImpCalcTail4(rPara
,rPoly
,rRect
); break;
545 bool SdrCaptionObj::BegCreate(SdrDragStat
& rStat
)
547 if (maRect
.IsEmpty()) return false; // Create currently only works with the given Rect
550 ImpGetCaptParams(aPara
);
551 maRect
.SetPos(rStat
.GetNow());
552 aTailPoly
[0]=rStat
.GetStart();
553 ImpCalcTail(aPara
,aTailPoly
,maRect
);
554 rStat
.SetActionRect(maRect
);
558 bool SdrCaptionObj::MovCreate(SdrDragStat
& rStat
)
561 ImpGetCaptParams(aPara
);
562 maRect
.SetPos(rStat
.GetNow());
563 ImpCalcTail(aPara
,aTailPoly
,maRect
);
564 rStat
.SetActionRect(maRect
);
570 bool SdrCaptionObj::EndCreate(SdrDragStat
& rStat
, SdrCreateCmd eCmd
)
573 ImpGetCaptParams(aPara
);
574 maRect
.SetPos(rStat
.GetNow());
575 ImpCalcTail(aPara
,aTailPoly
,maRect
);
577 return (eCmd
==SDRCREATE_FORCEEND
|| rStat
.GetPointAnz()>=2);
580 bool SdrCaptionObj::BckCreate(SdrDragStat
& /*rStat*/)
585 void SdrCaptionObj::BrkCreate(SdrDragStat
& /*rStat*/)
589 basegfx::B2DPolyPolygon
SdrCaptionObj::TakeCreatePoly(const SdrDragStat
& /*rDrag*/) const
591 basegfx::B2DPolyPolygon aRetval
;
592 const basegfx::B2DRange
aRange(maRect
.Left(), maRect
.Top(), maRect
.Right(), maRect
.Bottom());
593 aRetval
.append(basegfx::tools::createPolygonFromRect(aRange
));
594 aRetval
.append(aTailPoly
.getB2DPolygon());
598 Pointer
SdrCaptionObj::GetCreatePointer() const
600 return Pointer(PointerStyle::DrawCaption
);
603 void SdrCaptionObj::NbcMove(const Size
& rSiz
)
605 SdrRectObj::NbcMove(rSiz
);
606 MovePoly(aTailPoly
,rSiz
);
608 SetTailPos(GetFixedTailPos());
611 void SdrCaptionObj::NbcResize(const Point
& rRef
, const Fraction
& xFact
, const Fraction
& yFact
)
613 SdrRectObj::NbcResize(rRef
,xFact
,yFact
);
614 ResizePoly(aTailPoly
,rRef
,xFact
,yFact
);
617 SetTailPos(GetFixedTailPos());
620 void SdrCaptionObj::NbcSetRelativePos(const Point
& rPnt
)
622 Point
aRelPos0(aTailPoly
.GetPoint(0)-aAnchor
);
623 Size
aSiz(rPnt
.X()-aRelPos0
.X(),rPnt
.Y()-aRelPos0
.Y());
624 NbcMove(aSiz
); // This also calls SetRectsDirty()
627 Point
SdrCaptionObj::GetRelativePos() const
629 return aTailPoly
.GetPoint(0)-aAnchor
;
632 void SdrCaptionObj::NbcSetAnchorPos(const Point
& rPnt
)
634 SdrRectObj::NbcSetAnchorPos(rPnt
);
635 // TODO: Implementation missing.
638 const Point
& SdrCaptionObj::GetAnchorPos() const
640 // TODO: Implementation missing.
641 return SdrRectObj::GetAnchorPos();
644 void SdrCaptionObj::RecalcSnapRect()
646 SdrRectObj::RecalcSnapRect();
648 // TODO: Implementation missing.
651 const Rectangle
& SdrCaptionObj::GetSnapRect() const
653 return SdrRectObj::GetSnapRect();
656 void SdrCaptionObj::NbcSetSnapRect(const Rectangle
& rRect
)
659 // Move back to see the rectangle of the underlying SdrRectObj
660 // as the SnapRect, without the TailPos. That simplifies SnapRect
661 // handling again, if not allows it at all...
662 SdrRectObj::NbcSetSnapRect(rRect
);
665 const Rectangle
& SdrCaptionObj::GetLogicRect() const
670 void SdrCaptionObj::NbcSetLogicRect(const Rectangle
& rRect
)
672 SdrRectObj::NbcSetLogicRect(rRect
);
676 const Point
& SdrCaptionObj::GetTailPos() const
681 void SdrCaptionObj::SetTailPos(const Point
& rPos
)
683 if (aTailPoly
.GetSize()==0 || aTailPoly
[0]!=rPos
) {
684 Rectangle aBoundRect0
; if (pUserCall
!=NULL
) aBoundRect0
=GetLastBoundRect();
687 BroadcastObjectChange();
688 SendUserCall(SDRUSERCALL_RESIZE
,aBoundRect0
);
692 void SdrCaptionObj::NbcSetTailPos(const Point
& rPos
)
698 sal_uInt32
SdrCaptionObj::GetSnapPointCount() const
700 // TODO: Implementation missing.
704 Point
SdrCaptionObj::GetSnapPoint(sal_uInt32
/*i*/) const
706 // TODO: Implementation missing.
710 void SdrCaptionObj::SetModel(SdrModel
* pNewModel
)
712 SdrRectObj::SetModel(pNewModel
);
716 void SdrCaptionObj::Notify(SfxBroadcaster
& rBC
, const SfxHint
& rHint
)
718 SdrRectObj::Notify(rBC
,rHint
);
722 SdrObjGeoData
* SdrCaptionObj::NewGeoData() const
724 return new SdrCaptObjGeoData
;
727 void SdrCaptionObj::SaveGeoData(SdrObjGeoData
& rGeo
) const
729 SdrRectObj::SaveGeoData(rGeo
);
730 SdrCaptObjGeoData
& rCGeo
=static_cast<SdrCaptObjGeoData
&>(rGeo
);
731 rCGeo
.aTailPoly
=aTailPoly
;
734 void SdrCaptionObj::RestGeoData(const SdrObjGeoData
& rGeo
)
736 SdrRectObj::RestGeoData(rGeo
);
737 const SdrCaptObjGeoData
& rCGeo
=static_cast<const SdrCaptObjGeoData
&>(rGeo
);
738 aTailPoly
=rCGeo
.aTailPoly
;
741 SdrObject
* SdrCaptionObj::DoConvertToPolyObj(bool bBezier
, bool bAddText
) const
743 SdrObject
* pRect
=SdrRectObj::DoConvertToPolyObj(bBezier
, bAddText
);
744 SdrObject
* pTail
= ImpConvertMakeObj(basegfx::B2DPolyPolygon(aTailPoly
.getB2DPolygon()), false, bBezier
);
745 SdrObject
* pRet
=(pTail
!=NULL
) ? pTail
: pRect
;
746 if (pTail
!=NULL
&& pRect
!=NULL
) {
747 bool bInsRect
= true;
748 bool bInsTail
= true;
749 SdrObjList
* pOL
=pTail
->GetSubList();
750 if (pOL
!=NULL
) { pRet
=pRect
; bInsTail
= false; }
751 if (pOL
==NULL
) pOL
=pRect
->GetSubList();
752 if (pOL
!=NULL
) { pRet
=pRect
; bInsRect
= false; }
754 SdrObjGroup
* pGrp
=new SdrObjGroup
;
755 pOL
=pGrp
->GetSubList();
758 if (bInsRect
) pOL
->NbcInsertObject(pRect
);
759 if (bInsTail
) pOL
->NbcInsertObject(pTail
,0);
765 // Add own implementation for TRSetBaseGeometry to handle TailPos over changes.
766 void SdrCaptionObj::TRSetBaseGeometry(const basegfx::B2DHomMatrix
& rMatrix
, const basegfx::B2DPolyPolygon
& /*rPolyPolygon*/)
769 basegfx::B2DTuple aScale
;
770 basegfx::B2DTuple aTranslate
;
771 double fRotate
, fShearX
;
772 rMatrix
.decompose(aScale
, aTranslate
, fRotate
, fShearX
);
774 // #i75086# Old DrawingLayer (GeoStat and geometry) does not support holding negative scalings
775 // in X and Y which equal a 180 degree rotation. Recognize it and react accordingly
776 if(basegfx::fTools::less(aScale
.getX(), 0.0) && basegfx::fTools::less(aScale
.getY(), 0.0))
778 aScale
.setX(fabs(aScale
.getX()));
779 aScale
.setY(fabs(aScale
.getY()));
780 fRotate
= fmod(fRotate
+ F_PI
, F_2PI
);
783 // force metric to pool metric
784 SfxMapUnit eMapUnit
= pModel
->GetItemPool().GetMetric(0);
785 if(eMapUnit
!= SFX_MAPUNIT_100TH_MM
)
789 case SFX_MAPUNIT_TWIP
:
792 aTranslate
.setX(ImplMMToTwips(aTranslate
.getX()));
793 aTranslate
.setY(ImplMMToTwips(aTranslate
.getY()));
796 aScale
.setX(ImplMMToTwips(aScale
.getX()));
797 aScale
.setY(ImplMMToTwips(aScale
.getY()));
803 OSL_FAIL("TRSetBaseGeometry: Missing unit translation to PoolMetric!");
808 // if anchor is used, make position relative to it
809 if( pModel
->IsWriter() )
811 if(GetAnchorPos().X() || GetAnchorPos().Y())
813 aTranslate
+= basegfx::B2DTuple(GetAnchorPos().X(), GetAnchorPos().Y());
818 Point
aPoint(FRound(aTranslate
.getX()), FRound(aTranslate
.getY()));
819 Rectangle
aBaseRect(aPoint
, Size(FRound(aScale
.getX()), FRound(aScale
.getY())));
821 // set BaseRect, but rescue TailPos over this call
822 const Point aTailPoint
= GetTailPos();
823 SetSnapRect(aBaseRect
);
824 SetTailPos(aTailPoint
);
829 basegfx::B2DPolygon
SdrCaptionObj::getTailPolygon() const
831 return aTailPoly
.getB2DPolygon();
834 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */