1 /*************************************************************************
3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
5 * Copyright 2008 by Sun Microsystems, Inc.
7 * OpenOffice.org - a multi-platform office productivity suite
9 * $RCSfile: svdocapt.cxx,v $
10 * $Revision: 1.30.18.1 $
12 * This file is part of OpenOffice.org.
14 * OpenOffice.org is free software: you can redistribute it and/or modify
15 * it under the terms of the GNU Lesser General Public License version 3
16 * only, as published by the Free Software Foundation.
18 * OpenOffice.org is distributed in the hope that it will be useful,
19 * but WITHOUT ANY WARRANTY; without even the implied warranty of
20 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
21 * GNU Lesser General Public License version 3 for more details
22 * (a copy is included in the LICENSE file that accompanied this code).
24 * You should have received a copy of the GNU Lesser General Public License
25 * version 3 along with OpenOffice.org. If not, see
26 * <http://www.openoffice.org/license.html>
27 * for a copy of the LGPLv3 License.
29 ************************************************************************/
31 // MARKER(update_precomp.py): autogen include statement, do not remove
32 #include "precompiled_svx.hxx"
33 #include <tools/bigint.hxx>
34 #include <svx/xlnwtit.hxx>
35 #include <svtools/style.hxx>
36 #include <svx/svdocapt.hxx>
37 #include <svx/xpool.hxx>
38 #include <svx/xpoly.hxx>
39 #include <svx/svdattrx.hxx>
40 #include <svx/svdpool.hxx>
41 #include <svx/svdetc.hxx>
42 #include <svx/svdtrans.hxx>
43 #include <svx/svdhdl.hxx>
44 #include <svx/svddrag.hxx>
45 #include <svx/svdmodel.hxx>
46 #include <svx/svdview.hxx> // fuer RectSnap
47 #include "svdglob.hxx" // StringCache
48 #include "svdstr.hrc" // Objektname
49 #include <svx/svdogrp.hxx>
50 #include <svx/svdpage.hxx>
51 #include <svx/xflhtit.hxx>
52 #include <svx/xflclit.hxx>
53 #include <svx/xfltrit.hxx>
54 #include <svx/eeitem.hxx>
55 #include <svx/sdr/properties/captionproperties.hxx>
56 #include <vcl/salbtype.hxx> // FRound
57 #include <svx/sdr/contact/viewcontactofsdrcaptionobj.hxx>
58 #include <basegfx/tuple/b2dtuple.hxx>
59 #include <basegfx/matrix/b2dhommatrix.hxx>
60 #include <basegfx/polygon/b2dpolygon.hxx>
61 #include <basegfx/range/b2drange.hxx>
62 #include <basegfx/polygon/b2dpolygontools.hxx>
63 #include <svx/sdrhittesthelper.hxx>
66 inline double ImplTwipsToMM(double fVal
) { return (fVal
* (127.0 / 72.0)); }
67 inline double ImplMMToTwips(double fVal
) { return (fVal
* (72.0 / 127.0)); }
69 ////////////////////////////////////////////////////////////////////////////////////////////////////
71 enum EscDir
{LKS
,RTS
,OBN
,UNT
};
82 SdrCaptionEscDir eEscDir
;
94 eEscDir
=SDRCAPT_ESCHORIZONTAL
;
101 void CalcEscPos(const Point
& rTail
, const Rectangle
& rRect
, Point
& rPt
, EscDir
& rDir
) const;
104 void ImpCaptParams::CalcEscPos(const Point
& rTailPt
, const Rectangle
& rRect
, Point
& rPt
, EscDir
& rDir
) const
106 Point
aTl(rTailPt
); // lokal kopieren wg. Performance
109 nX
=rRect
.Right()-rRect
.Left();
110 nX
=BigMulDiv(nX
,nEscRel
,10000);
111 nY
=rRect
.Bottom()-rRect
.Top();
112 nY
=BigMulDiv(nY
,nEscRel
,10000);
121 FASTBOOL bTryH
=eEscDir
==SDRCAPT_ESCBESTFIT
;
123 if (eType
!=SDRCAPT_TYPE1
) {
124 bTryH
=eEscDir
==SDRCAPT_ESCHORIZONTAL
;
126 bTryH
=eEscDir
==SDRCAPT_ESCVERTICAL
;
129 FASTBOOL bTryV
=eEscDir
==SDRCAPT_ESCBESTFIT
;
131 if (eType
!=SDRCAPT_TYPE1
) {
132 bTryV
=eEscDir
==SDRCAPT_ESCVERTICAL
;
134 bTryV
=eEscDir
==SDRCAPT_ESCHORIZONTAL
;
139 Point
aLft(rRect
.Left()-nGap
,nY
);
140 Point
aRgt(rRect
.Right()+nGap
,nY
);
141 FASTBOOL bLft
=(aTl
.X()-aLft
.X()<aRgt
.X()-aTl
.X());
151 Point
aTop(nX
,rRect
.Top()-nGap
);
152 Point
aBtm(nX
,rRect
.Bottom()+nGap
);
153 FASTBOOL bTop
=(aTl
.Y()-aTop
.Y()<aBtm
.Y()-aTl
.Y());
163 FASTBOOL bTakeIt
=eEscDir
!=SDRCAPT_ESCBESTFIT
;
165 BigInt
aHorX(aBestPt
.X()-aTl
.X()); aHorX
*=aHorX
;
166 BigInt
aHorY(aBestPt
.Y()-aTl
.Y()); aHorY
*=aHorY
;
167 BigInt
aVerX(aBest2
.X()-aTl
.X()); aVerX
*=aVerX
;
168 BigInt
aVerY(aBest2
.Y()-aTl
.Y()); aVerY
*=aVerY
;
169 if (eType
!=SDRCAPT_TYPE1
) {
170 bTakeIt
=aVerX
+aVerY
<aHorX
+aHorY
;
172 bTakeIt
=aVerX
+aVerY
>=aHorX
+aHorY
;
184 //////////////////////////////////////////////////////////////////////////////
185 // BaseProperties section
187 sdr::properties::BaseProperties
* SdrCaptionObj::CreateObjectSpecificProperties()
189 return new sdr::properties::CaptionProperties(*this);
192 //////////////////////////////////////////////////////////////////////////////
193 // DrawContact section
195 sdr::contact::ViewContact
* SdrCaptionObj::CreateObjectSpecificViewContact()
197 return new sdr::contact::ViewContactOfSdrCaptionObj(*this);
200 //////////////////////////////////////////////////////////////////////////////
202 TYPEINIT1(SdrCaptionObj
,SdrRectObj
);
204 SdrCaptionObj::SdrCaptionObj():
205 SdrRectObj(OBJ_TEXT
),
206 aTailPoly(3), // Default Groesse: 3 Punkte = 2 Linien
207 mbSpecialTextBoxShadow(FALSE
),
212 SdrCaptionObj::SdrCaptionObj(const Rectangle
& rRect
):
213 SdrRectObj(OBJ_TEXT
,rRect
),
214 aTailPoly(3), // Default Groesse: 3 Punkte = 2 Linien
215 mbSpecialTextBoxShadow(FALSE
),
220 SdrCaptionObj::SdrCaptionObj(const Rectangle
& rRect
, const Point
& rTail
):
221 SdrRectObj(OBJ_TEXT
,rRect
),
222 aTailPoly(3), // Default Groesse: 3 Punkte = 2 Linien
223 mbSpecialTextBoxShadow(FALSE
),
226 aTailPoly
[0]=maFixedTailPos
=rTail
;
229 SdrCaptionObj::~SdrCaptionObj()
233 void SdrCaptionObj::TakeObjInfo(SdrObjTransformInfoRec
& rInfo
) const
235 rInfo
.bRotateFreeAllowed
=FALSE
;
236 rInfo
.bRotate90Allowed
=FALSE
;
237 rInfo
.bMirrorFreeAllowed
=FALSE
;
238 rInfo
.bMirror45Allowed
=FALSE
;
239 rInfo
.bMirror90Allowed
=FALSE
;
240 rInfo
.bTransparenceAllowed
= FALSE
;
241 rInfo
.bGradientAllowed
= FALSE
;
242 rInfo
.bShearAllowed
=FALSE
;
243 rInfo
.bEdgeRadiusAllowed
=FALSE
;
244 rInfo
.bCanConvToPath
=TRUE
;
245 rInfo
.bCanConvToPoly
=TRUE
;
246 rInfo
.bCanConvToPathLineToArea
=FALSE
;
247 rInfo
.bCanConvToPolyLineToArea
=FALSE
;
248 rInfo
.bCanConvToContour
= (rInfo
.bCanConvToPoly
|| LineGeometryUsageIsNecessary());
251 UINT16
SdrCaptionObj::GetObjIdentifier() const
253 return UINT16(OBJ_CAPTION
);
256 void SdrCaptionObj::operator=(const SdrObject
& rObj
)
258 SdrRectObj::operator=(rObj
);
259 aTailPoly
=((SdrCaptionObj
&)rObj
).aTailPoly
;
262 void SdrCaptionObj::TakeObjNameSingul(XubString
& rName
) const
264 rName
=ImpGetResStr(STR_ObjNameSingulCAPTION
);
266 String
aName( GetName() );
269 rName
+= sal_Unicode(' ');
270 rName
+= sal_Unicode('\'');
272 rName
+= sal_Unicode('\'');
276 void SdrCaptionObj::TakeObjNamePlural(XubString
& rName
) const
278 rName
=ImpGetResStr(STR_ObjNamePluralCAPTION
);
281 basegfx::B2DPolyPolygon
SdrCaptionObj::TakeXorPoly() const
283 basegfx::B2DPolyPolygon
aPolyPoly(SdrRectObj::TakeXorPoly());
284 aPolyPoly
.append(aTailPoly
.getB2DPolygon());
289 sal_uInt32
SdrCaptionObj::GetHdlCount() const
291 sal_uInt32
nAnz1(SdrRectObj::GetHdlCount());
292 // sal_uInt32 nAnz2(aTailPoly.GetSize());
293 // Derzeit ist nur das Draggen des Schwanzendes implementiert
297 SdrHdl
* SdrCaptionObj::GetHdl(sal_uInt32 nHdlNum
) const
299 const sal_uInt32
nRectHdlAnz(SdrRectObj::GetHdlCount());
301 if(nHdlNum
< nRectHdlAnz
)
303 return SdrRectObj::GetHdl(nHdlNum
);
307 sal_uInt32
nPntNum(nHdlNum
);
308 nPntNum
-= nRectHdlAnz
;
310 if(nPntNum
< aTailPoly
.GetSize())
312 SdrHdl
* pHdl
= new SdrHdl(aTailPoly
.GetPoint((sal_uInt16
)nPntNum
), HDL_POLY
);
313 pHdl
->SetPolyNum(1L);
314 pHdl
->SetPointNum(nPntNum
);
324 ////////////////////////////////////////////////////////////////////////////////////////////////////
326 bool SdrCaptionObj::hasSpecialDrag() const
331 bool SdrCaptionObj::beginSpecialDrag(SdrDragStat
& rDrag
) const
333 const SdrHdl
* pHdl
= rDrag
.GetHdl();
334 rDrag
.SetEndDragChangesAttributes(true);
335 rDrag
.SetEndDragChangesGeoAndAttributes(true);
337 if(pHdl
&& 0 == pHdl
->GetPolyNum())
339 return SdrRectObj::beginSpecialDrag(rDrag
);
343 rDrag
.SetOrtho8Possible(true);
350 rDrag
.SetNoSnap(true);
351 rDrag
.SetActionRect(aRect
);
353 Point
aHit(rDrag
.GetStart());
355 if(rDrag
.GetPageView() && SdrObjectPrimitiveHit(*this, aHit
, 0, *rDrag
.GetPageView(), 0, false))
362 if((1 == pHdl
->GetPolyNum()) && (0 == pHdl
->GetPointNum()))
370 bool SdrCaptionObj::applySpecialDrag(SdrDragStat
& rDrag
)
372 const SdrHdl
* pHdl
= rDrag
.GetHdl();
374 if(pHdl
&& 0 == pHdl
->GetPolyNum())
376 const bool bRet(SdrRectObj::applySpecialDrag(rDrag
));
384 Point
aDelt(rDrag
.GetNow()-rDrag
.GetStart());
388 aRect
.Move(aDelt
.X(),aDelt
.Y());
392 aTailPoly
[0] += aDelt
;
402 String
SdrCaptionObj::getSpecialDragComment(const SdrDragStat
& rDrag
) const
404 const SdrHdl
* pHdl
= rDrag
.GetHdl();
406 if(pHdl
&& 0 == pHdl
->GetPolyNum())
408 return SdrRectObj::getSpecialDragComment(rDrag
);
416 ImpTakeDescriptionStr(STR_DragCaptFram
, aStr
);
420 ImpTakeDescriptionStr(STR_DragCaptTail
, aStr
);
427 ////////////////////////////////////////////////////////////////////////////////////////////////////
429 void SdrCaptionObj::ImpGetCaptParams(ImpCaptParams
& rPara
) const
431 const SfxItemSet
& rSet
= GetObjectItemSet();
432 rPara
.eType
=((SdrCaptionTypeItem
&) (rSet
.Get(SDRATTR_CAPTIONTYPE
))).GetValue();
433 rPara
.bFixedAngle
=((SdrCaptionFixedAngleItem
&)(rSet
.Get(SDRATTR_CAPTIONANGLE
))).GetValue();
434 rPara
.nAngle
=((SdrCaptionAngleItem
&) (rSet
.Get(SDRATTR_CAPTIONFIXEDANGLE
))).GetValue();
435 rPara
.nGap
=((SdrCaptionGapItem
&) (rSet
.Get(SDRATTR_CAPTIONGAP
))).GetValue();
436 rPara
.eEscDir
=((SdrCaptionEscDirItem
&) (rSet
.Get(SDRATTR_CAPTIONESCDIR
))).GetValue();
437 rPara
.bEscRel
=((SdrCaptionEscIsRelItem
&) (rSet
.Get(SDRATTR_CAPTIONESCISREL
))).GetValue();
438 rPara
.nEscRel
=((SdrCaptionEscRelItem
&) (rSet
.Get(SDRATTR_CAPTIONESCREL
))).GetValue();
439 rPara
.nEscAbs
=((SdrCaptionEscAbsItem
&) (rSet
.Get(SDRATTR_CAPTIONESCABS
))).GetValue();
440 rPara
.nLineLen
=((SdrCaptionLineLenItem
&) (rSet
.Get(SDRATTR_CAPTIONLINELEN
))).GetValue();
441 rPara
.bFitLineLen
=((SdrCaptionFitLineLenItem
&)(rSet
.Get(SDRATTR_CAPTIONFITLINELEN
))).GetValue();
444 void SdrCaptionObj::ImpRecalcTail()
447 ImpGetCaptParams(aPara
);
448 ImpCalcTail(aPara
,aTailPoly
,aRect
);
454 // SdrCaptionObj::ImpCalcTail1 does move the object(!). What a hack.
455 // I really wonder why this had not triggered problems before. I am
456 // sure there are some places where SetTailPos() is called at least
457 // twice or SetSnapRect after it again just to work around this.
458 // Changed this method to not do that.
459 // Also found why this has been done: For interactive dragging of the
460 // tail end pos for SDRCAPT_TYPE1. This sure was the simplest method
461 // to achieve this, for the cost to make a whole group of const methods
462 // of this object implicitly chainging the object's position.
463 void SdrCaptionObj::ImpCalcTail1(const ImpCaptParams
& rPara
, Polygon
& rPoly
, Rectangle
& rRect
) const
474 rPara
.CalcEscPos(aTl
, rRect
, aEscPos
, eEscDir
);
477 if(eEscDir
==LKS
|| eEscDir
==RTS
)
479 aPol
[0].X() = aEscPos
.X();
483 aPol
[0].Y() = aEscPos
.Y();
489 void SdrCaptionObj::ImpCalcTail2(const ImpCaptParams
& rPara
, Polygon
& rPoly
, Rectangle
& rRect
) const
490 { // Gap/EscDir/EscPos/Angle
497 rPara
.CalcEscPos(aTl
,rRect
,aEscPos
,eEscDir
);
500 if (!rPara
.bFixedAngle
) {
501 // fehlende Implementation
506 void SdrCaptionObj::ImpCalcTail3(const ImpCaptParams
& rPara
, Polygon
& rPoly
, Rectangle
& rRect
) const
507 { // Gap/EscDir/EscPos/Angle/LineLen
514 rPara
.CalcEscPos(aTl
,rRect
,aEscPos
,eEscDir
);
518 if (eEscDir
==LKS
|| eEscDir
==RTS
) {
519 if (rPara
.bFitLineLen
) {
520 aPol
[1].X()=(aTl
.X()+aEscPos
.X())/2;
522 if (eEscDir
==LKS
) aPol
[1].X()-=rPara
.nLineLen
;
523 else aPol
[1].X()+=rPara
.nLineLen
;
526 if (rPara
.bFitLineLen
) {
527 aPol
[1].Y()=(aTl
.Y()+aEscPos
.Y())/2;
529 if (eEscDir
==OBN
) aPol
[1].Y()-=rPara
.nLineLen
;
530 else aPol
[1].Y()+=rPara
.nLineLen
;
533 if (!rPara
.bFixedAngle
) {
534 // fehlende Implementation
539 void SdrCaptionObj::ImpCalcTail4(const ImpCaptParams
& rPara
, Polygon
& rPoly
, Rectangle
& rRect
) const
541 ImpCalcTail3(rPara
,rPoly
,rRect
);
544 void SdrCaptionObj::ImpCalcTail(const ImpCaptParams
& rPara
, Polygon
& rPoly
, Rectangle
& rRect
) const
546 switch (rPara
.eType
) {
547 case SDRCAPT_TYPE1
: ImpCalcTail1(rPara
,rPoly
,rRect
); break;
548 case SDRCAPT_TYPE2
: ImpCalcTail2(rPara
,rPoly
,rRect
); break;
549 case SDRCAPT_TYPE3
: ImpCalcTail3(rPara
,rPoly
,rRect
); break;
550 case SDRCAPT_TYPE4
: ImpCalcTail4(rPara
,rPoly
,rRect
); break;
554 FASTBOOL
SdrCaptionObj::BegCreate(SdrDragStat
& rStat
)
556 if (aRect
.IsEmpty()) return FALSE
; // Create z.Zt. nur mit vorgegebenen Rect
559 ImpGetCaptParams(aPara
);
560 aRect
.SetPos(rStat
.GetNow());
561 aTailPoly
[0]=rStat
.GetStart();
562 ImpCalcTail(aPara
,aTailPoly
,aRect
);
563 rStat
.SetActionRect(aRect
);
567 FASTBOOL
SdrCaptionObj::MovCreate(SdrDragStat
& rStat
)
570 ImpGetCaptParams(aPara
);
571 aRect
.SetPos(rStat
.GetNow());
572 ImpCalcTail(aPara
,aTailPoly
,aRect
);
573 rStat
.SetActionRect(aRect
);
579 FASTBOOL
SdrCaptionObj::EndCreate(SdrDragStat
& rStat
, SdrCreateCmd eCmd
)
582 ImpGetCaptParams(aPara
);
583 aRect
.SetPos(rStat
.GetNow());
584 ImpCalcTail(aPara
,aTailPoly
,aRect
);
586 return (eCmd
==SDRCREATE_FORCEEND
|| rStat
.GetPointAnz()>=2);
589 FASTBOOL
SdrCaptionObj::BckCreate(SdrDragStat
& /*rStat*/)
594 void SdrCaptionObj::BrkCreate(SdrDragStat
& /*rStat*/)
598 basegfx::B2DPolyPolygon
SdrCaptionObj::TakeCreatePoly(const SdrDragStat
& /*rDrag*/) const
600 basegfx::B2DPolyPolygon aRetval
;
601 const basegfx::B2DRange
aRange(aRect
.Left(), aRect
.Top(), aRect
.Right(), aRect
.Bottom());
602 aRetval
.append(basegfx::tools::createPolygonFromRect(aRange
));
603 aRetval
.append(aTailPoly
.getB2DPolygon());
607 Pointer
SdrCaptionObj::GetCreatePointer() const
609 return Pointer(POINTER_DRAW_CAPTION
);
612 void SdrCaptionObj::NbcMove(const Size
& rSiz
)
614 SdrRectObj::NbcMove(rSiz
);
615 MovePoly(aTailPoly
,rSiz
);
617 SetTailPos(GetFixedTailPos());
620 void SdrCaptionObj::NbcResize(const Point
& rRef
, const Fraction
& xFact
, const Fraction
& yFact
)
622 SdrRectObj::NbcResize(rRef
,xFact
,yFact
);
623 ResizePoly(aTailPoly
,rRef
,xFact
,yFact
);
626 SetTailPos(GetFixedTailPos());
629 void SdrCaptionObj::NbcSetRelativePos(const Point
& rPnt
)
631 Point
aRelPos0(aTailPoly
.GetPoint(0)-aAnchor
);
632 Size
aSiz(rPnt
.X()-aRelPos0
.X(),rPnt
.Y()-aRelPos0
.Y());
633 NbcMove(aSiz
); // Der ruft auch das SetRectsDirty()
636 Point
SdrCaptionObj::GetRelativePos() const
638 return aTailPoly
.GetPoint(0)-aAnchor
;
641 void SdrCaptionObj::NbcSetAnchorPos(const Point
& rPnt
)
643 SdrRectObj::NbcSetAnchorPos(rPnt
);
644 // !!!!! fehlende Impl.
647 const Point
& SdrCaptionObj::GetAnchorPos() const
649 // !!!!! fehlende Impl.
650 return SdrRectObj::GetAnchorPos();
653 void SdrCaptionObj::RecalcSnapRect()
655 SdrRectObj::RecalcSnapRect();
657 // maSnapRect.Union(aTailPoly.GetBoundRect());
658 // !!!!! fehlende Impl.
661 const Rectangle
& SdrCaptionObj::GetSnapRect() const
663 return SdrRectObj::GetSnapRect();
666 void SdrCaptionObj::NbcSetSnapRect(const Rectangle
& rRect
)
669 // Move back to see the rectangle of the underlying SdrRectObj
670 // as the SnapRect, without the TailPos. That simplifies SnapRect
671 // handling again, if not allows it at all...
672 SdrRectObj::NbcSetSnapRect(rRect
);
675 const Rectangle
& SdrCaptionObj::GetLogicRect() const
680 void SdrCaptionObj::NbcSetLogicRect(const Rectangle
& rRect
)
682 SdrRectObj::NbcSetLogicRect(rRect
);
686 const Point
& SdrCaptionObj::GetTailPos() const
691 void SdrCaptionObj::SetTailPos(const Point
& rPos
)
693 if (aTailPoly
.GetSize()==0 || aTailPoly
[0]!=rPos
) {
694 Rectangle aBoundRect0
; if (pUserCall
!=NULL
) aBoundRect0
=GetLastBoundRect();
695 // #110094#-14 SendRepaintBroadcast();
698 BroadcastObjectChange();
699 SendUserCall(SDRUSERCALL_RESIZE
,aBoundRect0
);
703 void SdrCaptionObj::NbcSetTailPos(const Point
& rPos
)
709 sal_uInt32
SdrCaptionObj::GetSnapPointCount() const
711 // !!!!! fehlende Impl.
715 Point
SdrCaptionObj::GetSnapPoint(sal_uInt32
/*i*/) const
717 // !!!!! fehlende Impl.
721 void SdrCaptionObj::SetModel(SdrModel
* pNewModel
)
723 SdrRectObj::SetModel(pNewModel
);
727 void SdrCaptionObj::Notify(SfxBroadcaster
& rBC
, const SfxHint
& rHint
)
729 SdrRectObj::Notify(rBC
,rHint
);
733 SdrObjGeoData
* SdrCaptionObj::NewGeoData() const
735 return new SdrCaptObjGeoData
;
738 void SdrCaptionObj::SaveGeoData(SdrObjGeoData
& rGeo
) const
740 SdrRectObj::SaveGeoData(rGeo
);
741 SdrCaptObjGeoData
& rCGeo
=(SdrCaptObjGeoData
&)rGeo
;
742 rCGeo
.aTailPoly
=aTailPoly
;
745 void SdrCaptionObj::RestGeoData(const SdrObjGeoData
& rGeo
)
747 SdrRectObj::RestGeoData(rGeo
);
748 SdrCaptObjGeoData
& rCGeo
=(SdrCaptObjGeoData
&)rGeo
;
749 aTailPoly
=rCGeo
.aTailPoly
;
752 SdrObject
* SdrCaptionObj::DoConvertToPolyObj(BOOL bBezier
) const
753 { // #42334# - Convert implementiert
754 SdrObject
* pRect
=SdrRectObj::DoConvertToPolyObj(bBezier
);
755 SdrObject
* pTail
= ImpConvertMakeObj(basegfx::B2DPolyPolygon(aTailPoly
.getB2DPolygon()), sal_False
, bBezier
);
756 SdrObject
* pRet
=(pTail
!=NULL
) ? pTail
: pRect
;
757 if (pTail
!=NULL
&& pRect
!=NULL
) {
758 FASTBOOL bInsRect
=TRUE
;
759 FASTBOOL bInsTail
=TRUE
;
760 SdrObjList
* pOL
=pTail
->GetSubList();
761 if (pOL
!=NULL
) { pRet
=pRect
; bInsTail
=FALSE
; }
762 if (pOL
==NULL
) pOL
=pRect
->GetSubList();
763 if (pOL
!=NULL
) { pRet
=pRect
; bInsRect
=FALSE
; }
765 SdrObjGroup
* pGrp
=new SdrObjGroup
;
766 pOL
=pGrp
->GetSubList();
769 if (bInsRect
) pOL
->NbcInsertObject(pRect
);
770 if (bInsTail
) pOL
->NbcInsertObject(pTail
,0);
776 // Add own implementation for TRSetBaseGeometry to handle TailPos over changes.
777 void SdrCaptionObj::TRSetBaseGeometry(const basegfx::B2DHomMatrix
& rMatrix
, const basegfx::B2DPolyPolygon
& /*rPolyPolygon*/)
780 basegfx::B2DTuple aScale
;
781 basegfx::B2DTuple aTranslate
;
782 double fRotate
, fShearX
;
783 rMatrix
.decompose(aScale
, aTranslate
, fRotate
, fShearX
);
785 // #i75086# Old DrawingLayer (GeoStat and geometry) does not support holding negative scalings
786 // in X and Y which equal a 180 degree rotation. Recognize it and react accordingly
787 if(basegfx::fTools::less(aScale
.getX(), 0.0) && basegfx::fTools::less(aScale
.getY(), 0.0))
789 aScale
.setX(fabs(aScale
.getX()));
790 aScale
.setY(fabs(aScale
.getY()));
791 fRotate
= fmod(fRotate
+ F_PI
, F_2PI
);
794 // force metric to pool metric
795 SfxMapUnit eMapUnit
= pModel
->GetItemPool().GetMetric(0);
796 if(eMapUnit
!= SFX_MAPUNIT_100TH_MM
)
800 case SFX_MAPUNIT_TWIP
:
803 aTranslate
.setX(ImplMMToTwips(aTranslate
.getX()));
804 aTranslate
.setY(ImplMMToTwips(aTranslate
.getY()));
807 aScale
.setX(ImplMMToTwips(aScale
.getX()));
808 aScale
.setY(ImplMMToTwips(aScale
.getY()));
814 DBG_ERROR("TRSetBaseGeometry: Missing unit translation to PoolMetric!");
819 // if anchor is used, make position relative to it
820 if( pModel
->IsWriter() )
822 if(GetAnchorPos().X() || GetAnchorPos().Y())
824 aTranslate
+= basegfx::B2DTuple(GetAnchorPos().X(), GetAnchorPos().Y());
829 Point
aPoint(FRound(aTranslate
.getX()), FRound(aTranslate
.getY()));
830 Rectangle
aBaseRect(aPoint
, Size(FRound(aScale
.getX()), FRound(aScale
.getY())));
832 // set BaseRect, but rescue TailPos over this call
833 const Point aTailPoint
= GetTailPos();
834 SetSnapRect(aBaseRect
);
835 SetTailPos(aTailPoint
);
840 ::basegfx::B2DPolygon
SdrCaptionObj::getTailPolygon() const
842 return aTailPoly
.getB2DPolygon();