/************************************************************************* * * OpenOffice.org - a multi-platform office productivity suite * * $RCSfile: svdotext.cxx,v $ * * $Revision: 1.87 $ * * last change: $Author: kz $ $Date: 2008-04-04 12:50:20 $ * * The Contents of this file are made available subject to * the terms of GNU Lesser General Public License Version 2.1. * * * GNU Lesser General Public License Version 2.1 * ============================================= * Copyright 2005 by Sun Microsystems, Inc. * 901 San Antonio Road, Palo Alto, CA 94303, USA * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License version 2.1, as published by the Free Software Foundation. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, * MA 02111-1307 USA * ************************************************************************/ // MARKER(update_precomp.py): autogen include statement, do not remove #include "precompiled_svx.hxx" #include #include "svditext.hxx" #include // fuer Abfrage im Paint, ob das #include // Objekt gerade editiert wird #include // und fuer AnimationHandler (Laufschrift) #include "svdxout.hxx" #include "svdtouch.hxx" #include #include #include "svdscrol.hxx" // fuer Laufschrift #include // OutlinerDefaults #include "svdglob.hxx" // Stringcache #include "svdstr.hrc" // Objektname #include "svdtxhdl.hxx" // DrawTextToPath #include #include #ifndef INCLUDED_SVTOOLS_COLORCFG_HXX #include #endif #ifndef _EEITEM_HXX //autogen #include #endif #ifndef _EDITSTAT_HXX //autogen #include #endif #ifndef _OUTLOBJ_HXX //autogen #include #endif #ifndef _EDITOBJ_HXX //autogen #include #endif #ifndef _OUTLINER_HXX //autogen #include #endif #ifndef _SVX_FHGTITEM_HXX //autogen #include #endif #ifndef _SFXITEMPOOL_HXX //autogen #include #endif #ifndef _SVX_ADJITEM_HXX //autogen #include #endif #include #ifndef _SVX_XFTOUIT_HXX #include #endif #ifndef _SV_SALBTYPE_HXX #include // FRound #endif #ifndef _SVX_XFLGRIT_HXX #include #endif #ifndef _SVDPOOL_HXX #include #endif #ifndef _SVX_XFLCLIT_HXX #include #endif #ifndef _SFXSTYLE_HXX #include #endif #ifndef _MyEDITENG_HXX #include #endif #ifndef _SFXITEMITER_HXX #include #endif #ifndef _SDR_PROPERTIES_TEXTPROPERTIES_HXX #include #endif // #110496# #ifndef _SV_METAACT_HXX #include #endif // #111111# #ifndef _SDR_CONTACT_VIEWCONTACTOFTEXTOBJ_HXX #include #endif #ifndef _BGFX_TUPLE_B2DTUPLE_HXX #include #endif #ifndef _BGFX_MATRIX_B2DHOMMATRIX_HXX #include #endif #ifndef _BGFX_POLYGON_B2DPOLYGON_HXX #include #endif // #104018# replace macros above with type-safe methods inline double ImplTwipsToMM(double fVal) { return (fVal * (127.0 / 72.0)); } inline double ImplMMToTwips(double fVal) { return (fVal * (72.0 / 127.0)); } //////////////////////////////////////////////////////////////////////////////////////////////////// // // @@@@@@ @@@@@ @@ @@ @@@@@@ @@@@ @@@@@ @@@@@@ // @@ @@ @@@ @@@ @@ @@ @@ @@ @@ @@ // @@ @@ @@@@@ @@ @@ @@ @@ @@ @@ // @@ @@@@ @@@ @@ @@ @@ @@@@@ @@ // @@ @@ @@@@@ @@ @@ @@ @@ @@ @@ // @@ @@ @@@ @@@ @@ @@ @@ @@ @@ @@ @@ // @@ @@@@@ @@ @@ @@ @@@@ @@@@@ @@@@ // //////////////////////////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////// // BaseProperties section sdr::properties::BaseProperties* SdrTextObj::CreateObjectSpecificProperties() { return new sdr::properties::TextProperties(*this); } ////////////////////////////////////////////////////////////////////////////// // DrawContact section sdr::contact::ViewContact* SdrTextObj::CreateObjectSpecificViewContact() { return new sdr::contact::ViewContactOfTextObj(*this); } ////////////////////////////////////////////////////////////////////////////// TYPEINIT1(SdrTextObj,SdrAttrObj); SdrTextObj::SdrTextObj() : SdrAttrObj(), mpText(NULL), pEdtOutl(NULL), pFormTextBoundRect(NULL), eTextKind(OBJ_TEXT) { bTextSizeDirty=FALSE; bTextFrame=FALSE; bNoShear=FALSE; bNoRotate=FALSE; bNoMirror=FALSE; bDisableAutoWidthOnDragging=FALSE; // #101684# mbInEditMode = FALSE; // #111096# mbTextHidden = sal_False; // #111096# mbTextAnimationAllowed = sal_True; // #108784# maTextEditOffset = Point(0, 0); // #i25616# mbSupportTextIndentingOnLineWidthChange = sal_True; } SdrTextObj::SdrTextObj(const Rectangle& rNewRect) : SdrAttrObj(), aRect(rNewRect), mpText(NULL), pEdtOutl(NULL), pFormTextBoundRect(NULL) { bTextSizeDirty=FALSE; bTextFrame=FALSE; bNoShear=FALSE; bNoRotate=FALSE; bNoMirror=FALSE; bDisableAutoWidthOnDragging=FALSE; ImpJustifyRect(aRect); // #101684# mbInEditMode = FALSE; // #111096# mbTextHidden = sal_False; // #111096# mbTextAnimationAllowed = sal_True; // #108784# maTextEditOffset = Point(0, 0); // #i25616# mbSupportTextIndentingOnLineWidthChange = sal_True; } SdrTextObj::SdrTextObj(SdrObjKind eNewTextKind) : SdrAttrObj(), mpText(NULL), pEdtOutl(NULL), pFormTextBoundRect(NULL), eTextKind(eNewTextKind) { bTextSizeDirty=FALSE; bTextFrame=TRUE; bNoShear=TRUE; bNoRotate=FALSE; bNoMirror=TRUE; bDisableAutoWidthOnDragging=FALSE; // #101684# mbInEditMode = FALSE; // #111096# mbTextHidden = sal_False; // #111096# mbTextAnimationAllowed = sal_True; // #108784# maTextEditOffset = Point(0, 0); // #i25616# mbSupportTextIndentingOnLineWidthChange = sal_True; } SdrTextObj::SdrTextObj(SdrObjKind eNewTextKind, const Rectangle& rNewRect) : SdrAttrObj(), aRect(rNewRect), mpText(NULL), pEdtOutl(NULL), pFormTextBoundRect(NULL), eTextKind(eNewTextKind) { bTextSizeDirty=FALSE; bTextFrame=TRUE; bNoShear=TRUE; bNoRotate=FALSE; bNoMirror=TRUE; bDisableAutoWidthOnDragging=FALSE; ImpJustifyRect(aRect); // #101684# mbInEditMode = FALSE; // #111096# mbTextHidden = sal_False; // #111096# mbTextAnimationAllowed = sal_True; // #108784# maTextEditOffset = Point(0, 0); // #i25616# mbSupportTextIndentingOnLineWidthChange = sal_True; } SdrTextObj::SdrTextObj(SdrObjKind eNewTextKind, const Rectangle& rNewRect, SvStream& rInput, const String& rBaseURL, USHORT eFormat) : SdrAttrObj(), aRect(rNewRect), mpText(NULL), pEdtOutl(NULL), pFormTextBoundRect(NULL), eTextKind(eNewTextKind) { bTextSizeDirty=FALSE; bTextFrame=TRUE; bNoShear=TRUE; bNoRotate=FALSE; bNoMirror=TRUE; bDisableAutoWidthOnDragging=FALSE; ImpJustifyRect(aRect); NbcSetText(rInput, rBaseURL, eFormat); // #101684# mbInEditMode = FALSE; // #111096# mbTextHidden = sal_False; // #111096# mbTextAnimationAllowed = sal_True; // #108784# maTextEditOffset = Point(0, 0); // #i25616# mbSupportTextIndentingOnLineWidthChange = sal_True; } SdrTextObj::~SdrTextObj() { if( pModel ) { SdrOutliner& rOutl = pModel->GetHitTestOutliner(); if( rOutl.GetTextObj() == this ) rOutl.SetTextObj( NULL ); } if(mpText!=NULL) delete mpText; if (pFormTextBoundRect!=NULL) delete pFormTextBoundRect; ImpLinkAbmeldung(); } void SdrTextObj::FitFrameToTextSize() { DBG_ASSERT(pModel!=NULL,"SdrTextObj::FitFrameToTextSize(): pModel=NULL!") ImpJustifyRect(aRect); SdrText* pText = getActiveText(); if( pText!=NULL && pText->GetOutlinerParaObject() && pModel!=NULL) { SdrOutliner& rOutliner=ImpGetDrawOutliner(); rOutliner.SetPaperSize(Size(aRect.Right()-aRect.Left(),aRect.Bottom()-aRect.Top())); rOutliner.SetUpdateMode(TRUE); rOutliner.SetText(*pText->GetOutlinerParaObject()); Rectangle aTextRect; Size aNewSize(rOutliner.CalcTextSize()); rOutliner.Clear(); aNewSize.Width()++; // wegen evtl. Rundungsfehler aNewSize.Width()+=GetTextLeftDistance()+GetTextRightDistance(); aNewSize.Height()+=GetTextUpperDistance()+GetTextLowerDistance(); Rectangle aNewRect(aRect); aNewRect.SetSize(aNewSize); ImpJustifyRect(aNewRect); if (aNewRect!=aRect) { SetLogicRect(aNewRect); } } } void SdrTextObj::NbcSetText(const XubString& rStr) { SdrOutliner& rOutliner=ImpGetDrawOutliner(); rOutliner.SetStyleSheet( 0, GetStyleSheet()); //OutputDevice* pRef1=rOutliner.GetRefDevice(); rOutliner.SetUpdateMode(TRUE); rOutliner.SetText(rStr,rOutliner.GetParagraph( 0 )); OutlinerParaObject* pNewText=rOutliner.CreateParaObject(); Size aSiz(rOutliner.CalcTextSize()); //OutputDevice* pRef2=rOutliner.GetRefDevice(); rOutliner.Clear(); NbcSetOutlinerParaObject(pNewText); aTextSize=aSiz; bTextSizeDirty=FALSE; } void SdrTextObj::SetText(const XubString& rStr) { Rectangle aBoundRect0; if (pUserCall!=NULL) aBoundRect0=GetLastBoundRect(); // #110094#-14 SendRepaintBroadcast(); NbcSetText(rStr); SetChanged(); BroadcastObjectChange(); SendUserCall(SDRUSERCALL_RESIZE,aBoundRect0); //if (GetBoundRect()!=aBoundRect0) { // SendUserCall(SDRUSERCALL_RESIZE,aBoundRect0); //} } void SdrTextObj::NbcSetText(SvStream& rInput, const String& rBaseURL, USHORT eFormat) { SdrOutliner& rOutliner=ImpGetDrawOutliner(); rOutliner.SetStyleSheet( 0, GetStyleSheet()); rOutliner.Read(rInput,rBaseURL,eFormat); OutlinerParaObject* pNewText=rOutliner.CreateParaObject(); rOutliner.SetUpdateMode(TRUE); Size aSiz(rOutliner.CalcTextSize()); rOutliner.Clear(); NbcSetOutlinerParaObject(pNewText); aTextSize=aSiz; bTextSizeDirty=FALSE; } void SdrTextObj::SetText(SvStream& rInput, const String& rBaseURL, USHORT eFormat) { Rectangle aBoundRect0; if (pUserCall!=NULL) aBoundRect0=GetLastBoundRect(); // #110094#-14 SendRepaintBroadcast(); NbcSetText(rInput,rBaseURL,eFormat); SetChanged(); BroadcastObjectChange(); SendUserCall(SDRUSERCALL_RESIZE,aBoundRect0); } const Size& SdrTextObj::GetTextSize() const { if (bTextSizeDirty) { Size aSiz; SdrText* pText = getActiveText(); if( pText && pText->GetOutlinerParaObject ()) { SdrOutliner& rOutliner=ImpGetDrawOutliner(); rOutliner.SetText(*pText->GetOutlinerParaObject()); rOutliner.SetUpdateMode(TRUE); aSiz=rOutliner.CalcTextSize(); rOutliner.Clear(); } // 2x casting auf nonconst ((SdrTextObj*)this)->aTextSize=aSiz; ((SdrTextObj*)this)->bTextSizeDirty=FALSE; } return aTextSize; } FASTBOOL SdrTextObj::IsAutoGrowHeight() const { if(!bTextFrame) return FALSE; // AutoGrow nur bei TextFrames const SfxItemSet& rSet = GetObjectItemSet(); BOOL bRet = ((SdrTextAutoGrowHeightItem&)(rSet.Get(SDRATTR_TEXT_AUTOGROWHEIGHT))).GetValue(); if(bRet) { SdrTextAniKind eAniKind = ((SdrTextAniKindItem&)(rSet.Get(SDRATTR_TEXT_ANIKIND))).GetValue(); if(eAniKind == SDRTEXTANI_SCROLL || eAniKind == SDRTEXTANI_ALTERNATE || eAniKind == SDRTEXTANI_SLIDE) { SdrTextAniDirection eDirection = ((SdrTextAniDirectionItem&)(rSet.Get(SDRATTR_TEXT_ANIDIRECTION))).GetValue(); if(eDirection == SDRTEXTANI_UP || eDirection == SDRTEXTANI_DOWN) { bRet = FALSE; } } } return bRet; } FASTBOOL SdrTextObj::IsAutoGrowWidth() const { if(!bTextFrame) return FALSE; // AutoGrow nur bei TextFrames const SfxItemSet& rSet = GetObjectItemSet(); BOOL bRet = ((SdrTextAutoGrowHeightItem&)(rSet.Get(SDRATTR_TEXT_AUTOGROWWIDTH))).GetValue(); // #101684# BOOL bInEditMOde = IsInEditMode(); if(!bInEditMOde && bRet) { SdrTextAniKind eAniKind = ((SdrTextAniKindItem&)(rSet.Get(SDRATTR_TEXT_ANIKIND))).GetValue(); if(eAniKind == SDRTEXTANI_SCROLL || eAniKind == SDRTEXTANI_ALTERNATE || eAniKind == SDRTEXTANI_SLIDE) { SdrTextAniDirection eDirection = ((SdrTextAniDirectionItem&)(rSet.Get(SDRATTR_TEXT_ANIDIRECTION))).GetValue(); if(eDirection == SDRTEXTANI_LEFT || eDirection == SDRTEXTANI_RIGHT) { bRet = FALSE; } } } return bRet; } SdrTextHorzAdjust SdrTextObj::GetTextHorizontalAdjust() const { if(IsContourTextFrame()) return SDRTEXTHORZADJUST_BLOCK; const SfxItemSet& rSet = GetObjectItemSet(); SdrTextHorzAdjust eRet = ((SdrTextHorzAdjustItem&)(rSet.Get(SDRATTR_TEXT_HORZADJUST))).GetValue(); // #101684# BOOL bInEditMode = IsInEditMode(); if(!bInEditMode && eRet == SDRTEXTHORZADJUST_BLOCK) { SdrTextAniKind eAniKind = ((SdrTextAniKindItem&)(rSet.Get(SDRATTR_TEXT_ANIKIND))).GetValue(); if(eAniKind == SDRTEXTANI_SCROLL || eAniKind == SDRTEXTANI_ALTERNATE || eAniKind == SDRTEXTANI_SLIDE) { SdrTextAniDirection eDirection = ((SdrTextAniDirectionItem&)(rSet.Get(SDRATTR_TEXT_ANIDIRECTION))).GetValue(); if(eDirection == SDRTEXTANI_LEFT || eDirection == SDRTEXTANI_RIGHT) { eRet = SDRTEXTHORZADJUST_LEFT; } } } return eRet; } // defaults: BLOCK fuer Textrahmen, CENTER fuer beschriftete Grafikobjekte SdrTextVertAdjust SdrTextObj::GetTextVerticalAdjust() const { if(IsContourTextFrame()) return SDRTEXTVERTADJUST_TOP; // #103516# Take care for vertical text animation here const SfxItemSet& rSet = GetObjectItemSet(); SdrTextVertAdjust eRet = ((SdrTextVertAdjustItem&)(rSet.Get(SDRATTR_TEXT_VERTADJUST))).GetValue(); BOOL bInEditMode = IsInEditMode(); // #103516# Take care for vertical text animation here if(!bInEditMode && eRet == SDRTEXTVERTADJUST_BLOCK) { SdrTextAniKind eAniKind = ((SdrTextAniKindItem&)(rSet.Get(SDRATTR_TEXT_ANIKIND))).GetValue(); if(eAniKind == SDRTEXTANI_SCROLL || eAniKind == SDRTEXTANI_ALTERNATE || eAniKind == SDRTEXTANI_SLIDE) { SdrTextAniDirection eDirection = ((SdrTextAniDirectionItem&)(rSet.Get(SDRATTR_TEXT_ANIDIRECTION))).GetValue(); if(eDirection == SDRTEXTANI_LEFT || eDirection == SDRTEXTANI_RIGHT) { eRet = SDRTEXTVERTADJUST_TOP; } } } return eRet; } // defaults: TOP fuer Textrahmen, CENTER fuer beschriftete Grafikobjekte void SdrTextObj::ImpJustifyRect(Rectangle& rRect) const { if (!rRect.IsEmpty()) { rRect.Justify(); if (rRect.Left()==rRect.Right()) rRect.Right()++; if (rRect.Top()==rRect.Bottom()) rRect.Bottom()++; } } void SdrTextObj::ImpCheckShear() { if (bNoShear && aGeo.nShearWink!=0) { aGeo.nShearWink=0; aGeo.nTan=0; } } void SdrTextObj::TakeObjInfo(SdrObjTransformInfoRec& rInfo) const { FASTBOOL bNoTextFrame=!IsTextFrame(); rInfo.bResizeFreeAllowed=bNoTextFrame || aGeo.nDrehWink%9000==0; rInfo.bResizePropAllowed=TRUE; rInfo.bRotateFreeAllowed=TRUE; rInfo.bRotate90Allowed =TRUE; rInfo.bMirrorFreeAllowed=bNoTextFrame; rInfo.bMirror45Allowed =bNoTextFrame; rInfo.bMirror90Allowed =bNoTextFrame; // allow transparence rInfo.bTransparenceAllowed = TRUE; // gradient depends on fillstyle XFillStyle eFillStyle = ((XFillStyleItem&)(GetObjectItem(XATTR_FILLSTYLE))).GetValue(); rInfo.bGradientAllowed = (eFillStyle == XFILL_GRADIENT); rInfo.bShearAllowed =bNoTextFrame; rInfo.bEdgeRadiusAllowed=TRUE; FASTBOOL bCanConv=ImpCanConvTextToCurve(); rInfo.bCanConvToPath =bCanConv; rInfo.bCanConvToPoly =bCanConv; rInfo.bCanConvToPathLineToArea=bCanConv; rInfo.bCanConvToPolyLineToArea=bCanConv; rInfo.bCanConvToContour = (rInfo.bCanConvToPoly || LineGeometryUsageIsNecessary()); } UINT16 SdrTextObj::GetObjIdentifier() const { return USHORT(eTextKind); } bool SdrTextObj::HasTextImpl( SdrOutliner* pOutliner ) { bool bRet=false; if(pOutliner) { Paragraph* p1stPara=pOutliner->GetParagraph( 0 ); ULONG nParaAnz=pOutliner->GetParagraphCount(); if(p1stPara==NULL) nParaAnz=0; if(nParaAnz==1) { // if it is only one paragraph, check if that paragraph is empty XubString aStr(pOutliner->GetText(p1stPara)); if(!aStr.Len()) nParaAnz = 0; } bRet= nParaAnz!=0; } return bRet; } FASTBOOL SdrTextObj::HasEditText() const { return HasTextImpl( pEdtOutl ); } void SdrTextObj::SetPage(SdrPage* pNewPage) { FASTBOOL bRemove=pNewPage==NULL && pPage!=NULL; FASTBOOL bInsert=pNewPage!=NULL && pPage==NULL; FASTBOOL bLinked=IsLinkedText(); if (bLinked && bRemove) { ImpLinkAbmeldung(); } SdrAttrObj::SetPage(pNewPage); if (bLinked && bInsert) { ImpLinkAnmeldung(); } } void SdrTextObj::SetModel(SdrModel* pNewModel) { SdrModel* pOldModel=pModel; bool bLinked=IsLinkedText(); bool bChg=pNewModel!=pModel; if (bLinked && bChg) { ImpLinkAbmeldung(); } SdrAttrObj::SetModel(pNewModel); if( bChg ) { if( pNewModel != 0 && pOldModel != 0 ) SetTextSizeDirty(); sal_Int32 nCount = getTextCount(); for( sal_Int32 nText = 0; nText < nCount; nText++ ) { SdrText* pText = getText( nText ); if( pText ) pText->SetModel( pNewModel ); } } if (bLinked && bChg) { ImpLinkAnmeldung(); } } FASTBOOL SdrTextObj::NbcSetEckenradius(long nRad) { SetObjectItem(SdrEckenradiusItem(nRad)); return TRUE; } FASTBOOL SdrTextObj::NbcSetAutoGrowHeight(bool bAuto) { if(bTextFrame) { SetObjectItem(SdrTextAutoGrowHeightItem(bAuto)); return TRUE; } return FALSE; } FASTBOOL SdrTextObj::NbcSetMinTextFrameHeight(long nHgt) { if( bTextFrame && ( !pModel || !pModel->isLocked() ) ) // SJ: #i44922# { SetObjectItem(SdrTextMinFrameHeightItem(nHgt)); // #84974# use bDisableAutoWidthOnDragging as // bDisableAutoHeightOnDragging if vertical. if(IsVerticalWriting() && bDisableAutoWidthOnDragging) { bDisableAutoWidthOnDragging = FALSE; SetObjectItem(SdrTextAutoGrowHeightItem(FALSE)); } return TRUE; } return FALSE; } FASTBOOL SdrTextObj::NbcSetMaxTextFrameHeight(long nHgt) { if(bTextFrame) { SetObjectItem(SdrTextMaxFrameHeightItem(nHgt)); return TRUE; } return FALSE; } FASTBOOL SdrTextObj::NbcSetAutoGrowWidth(bool bAuto) { if(bTextFrame) { SetObjectItem(SdrTextAutoGrowWidthItem(bAuto)); return TRUE; } return FALSE; } FASTBOOL SdrTextObj::NbcSetMinTextFrameWidth(long nWdt) { if( bTextFrame && ( !pModel || !pModel->isLocked() ) ) // SJ: #i44922# { SetObjectItem(SdrTextMinFrameWidthItem(nWdt)); // #84974# use bDisableAutoWidthOnDragging only // when not vertical. if(!IsVerticalWriting() && bDisableAutoWidthOnDragging) { bDisableAutoWidthOnDragging = FALSE; SetObjectItem(SdrTextAutoGrowWidthItem(FALSE)); } return TRUE; } return FALSE; } FASTBOOL SdrTextObj::NbcSetMaxTextFrameWidth(long nWdt) { if(bTextFrame) { SetObjectItem(SdrTextMaxFrameWidthItem(nWdt)); return TRUE; } return FALSE; } FASTBOOL SdrTextObj::NbcSetFitToSize(SdrFitToSizeType eFit) { if(bTextFrame) { SetObjectItem(SdrTextFitToSizeTypeItem(eFit)); return TRUE; } return FALSE; } void SdrTextObj::ImpSetContourPolygon( SdrOutliner& rOutliner, Rectangle& rAnchorRect, BOOL bLineWidth ) const { basegfx::B2DPolyPolygon aXorPolyPolygon(TakeXorPoly(FALSE)); basegfx::B2DPolyPolygon* pContourPolyPolygon = 0L; basegfx::B2DHomMatrix aMatrix; aMatrix.translate(-rAnchorRect.Left(), -rAnchorRect.Top()); if(aGeo.nDrehWink) { // Unrotate! aMatrix.rotate(-aGeo.nDrehWink * nPi180); } aXorPolyPolygon.transform(aMatrix); if( bLineWidth ) { // Strichstaerke beruecksichtigen // Beim Hittest muss das unterbleiben (Performance!) pContourPolyPolygon = new basegfx::B2DPolyPolygon(); // #86258# test if shadow needs to be avoided for TakeContour() const SfxItemSet& rSet = GetObjectItemSet(); sal_Bool bShadowOn = ((SdrShadowItem&)(rSet.Get(SDRATTR_SHADOW))).GetValue(); // #i33696# // Remember TextObject currently set at the DrawOutliner, it WILL be // replaced during calculating the outline since it uses an own paint // and that one uses the DrawOutliner, too. const SdrTextObj* pLastTextObject = rOutliner.GetTextObj(); if(bShadowOn) { // #86258# force shadow off SdrObject* pCopy = Clone(); pCopy->SetMergedItem(SdrShadowItem(FALSE)); *pContourPolyPolygon = pCopy->TakeContour(); SdrObject::Free( pCopy ); } else { *pContourPolyPolygon = TakeContour(); } // #i33696# // restore remembered text object if(pLastTextObject != rOutliner.GetTextObj()) { rOutliner.SetTextObj(pLastTextObject); } pContourPolyPolygon->transform(aMatrix); } rOutliner.SetPolygon(aXorPolyPolygon, pContourPolyPolygon); } void SdrTextObj::TakeUnrotatedSnapRect(Rectangle& rRect) const { rRect=aRect; } void SdrTextObj::TakeTextAnchorRect(Rectangle& rAnchorRect) const { long nLeftDist=GetTextLeftDistance(); long nRightDist=GetTextRightDistance(); long nUpperDist=GetTextUpperDistance(); long nLowerDist=GetTextLowerDistance(); Rectangle aAnkRect(aRect); // Rect innerhalb dem geankert wird FASTBOOL bFrame=IsTextFrame(); if (!bFrame) { TakeUnrotatedSnapRect(aAnkRect); } Point aRotateRef(aAnkRect.TopLeft()); aAnkRect.Left()+=nLeftDist; aAnkRect.Top()+=nUpperDist; aAnkRect.Right()-=nRightDist; aAnkRect.Bottom()-=nLowerDist; // #108816# // Since sizes may be bigger than the object bounds it is necessary to // justify the rect now. ImpJustifyRect(aAnkRect); if (bFrame) { // !!! hier noch etwas verfeinern !!! if (aAnkRect.GetWidth()<2) aAnkRect.Right()=aAnkRect.Left()+1; // Mindestgroesse 2 if (aAnkRect.GetHeight()<2) aAnkRect.Bottom()=aAnkRect.Top()+1; // Mindestgroesse 2 } if (aGeo.nDrehWink!=0) { Point aTmpPt(aAnkRect.TopLeft()); RotatePoint(aTmpPt,aRotateRef,aGeo.nSin,aGeo.nCos); aTmpPt-=aAnkRect.TopLeft(); aAnkRect.Move(aTmpPt.X(),aTmpPt.Y()); } rAnchorRect=aAnkRect; } void SdrTextObj::TakeTextRect( SdrOutliner& rOutliner, Rectangle& rTextRect, FASTBOOL bNoEditText, Rectangle* pAnchorRect, BOOL bLineWidth ) const { Rectangle aAnkRect; // Rect innerhalb dem geankert wird TakeTextAnchorRect(aAnkRect); SdrTextVertAdjust eVAdj=GetTextVerticalAdjust(); SdrTextHorzAdjust eHAdj=GetTextHorizontalAdjust(); SdrTextAniKind eAniKind=GetTextAniKind(); SdrTextAniDirection eAniDirection=GetTextAniDirection(); SdrFitToSizeType eFit=GetFitToSize(); FASTBOOL bFitToSize=(eFit==SDRTEXTFIT_PROPORTIONAL || eFit==SDRTEXTFIT_ALLLINES); FASTBOOL bContourFrame=IsContourTextFrame(); FASTBOOL bFrame=IsTextFrame(); ULONG nStat0=rOutliner.GetControlWord(); Size aNullSize; if (!bContourFrame) { rOutliner.SetControlWord(nStat0|EE_CNTRL_AUTOPAGESIZE); rOutliner.SetMinAutoPaperSize(aNullSize); rOutliner.SetMaxAutoPaperSize(Size(1000000,1000000)); } if (!bFitToSize && !bContourFrame) { long nAnkWdt=aAnkRect.GetWidth(); long nAnkHgt=aAnkRect.GetHeight(); if (bFrame) { long nWdt=nAnkWdt; long nHgt=nAnkHgt; // #101684# BOOL bInEditMode = IsInEditMode(); if (!bInEditMode && (eAniKind==SDRTEXTANI_SCROLL || eAniKind==SDRTEXTANI_ALTERNATE || eAniKind==SDRTEXTANI_SLIDE)) { // Grenzenlose Papiergroesse fuer Laufschrift if (eAniDirection==SDRTEXTANI_LEFT || eAniDirection==SDRTEXTANI_RIGHT) nWdt=1000000; if (eAniDirection==SDRTEXTANI_UP || eAniDirection==SDRTEXTANI_DOWN) nHgt=1000000; } rOutliner.SetMaxAutoPaperSize(Size(nWdt,nHgt)); } // #103516# New try with _BLOCK for hor and ver after completely // supporting full width for vertical text. if(SDRTEXTHORZADJUST_BLOCK == eHAdj && !IsVerticalWriting()) { rOutliner.SetMinAutoPaperSize(Size(nAnkWdt, 0)); } if(SDRTEXTVERTADJUST_BLOCK == eVAdj && IsVerticalWriting()) { rOutliner.SetMinAutoPaperSize(Size(0, nAnkHgt)); } } rOutliner.SetPaperSize(aNullSize); if (bContourFrame) ImpSetContourPolygon( rOutliner, aAnkRect, bLineWidth ); // put text into the outliner, if available from the edit outliner SdrText* pText = getActiveText(); OutlinerParaObject* pOutlinerParaObject = pText ? pText->GetOutlinerParaObject() : 0; OutlinerParaObject* pPara = (pEdtOutl && !bNoEditText) ? pEdtOutl->CreateParaObject() : pOutlinerParaObject; if (pPara) { BOOL bHitTest = FALSE; if( pModel ) bHitTest = &pModel->GetHitTestOutliner() == &rOutliner; const SdrTextObj* pTestObj = rOutliner.GetTextObj(); if( !pTestObj || !bHitTest || pTestObj != this || pTestObj->GetOutlinerParaObject() != pOutlinerParaObject ) { if( bHitTest ) // #i33696# take back fix #i27510# rOutliner.SetTextObj( this ); rOutliner.SetUpdateMode(TRUE); rOutliner.SetText(*pPara); } } else { rOutliner.SetTextObj( NULL ); } if (pEdtOutl && !bNoEditText && pPara) delete pPara; rOutliner.SetUpdateMode(TRUE); rOutliner.SetControlWord(nStat0); if( pText ) pText->CheckPortionInfo(rOutliner); Point aTextPos(aAnkRect.TopLeft()); Size aTextSiz(rOutliner.GetPaperSize()); // GetPaperSize() hat etwas Toleranz drauf, oder? // #106653# // For draw objects containing text correct hor/ver alignment if text is bigger // than the object itself. Without that correction, the text would always be // formatted to the left edge (or top edge when vertical) of the draw object. if(!IsTextFrame()) { if(aAnkRect.GetWidth() < aTextSiz.Width() && !IsVerticalWriting()) { // #110129# // Horizontal case here. Correct only if eHAdj == SDRTEXTHORZADJUST_BLOCK, // else the alignment is wanted. if(SDRTEXTHORZADJUST_BLOCK == eHAdj) { eHAdj = SDRTEXTHORZADJUST_CENTER; } } if(aAnkRect.GetHeight() < aTextSiz.Height() && IsVerticalWriting()) { // #110129# // Vertical case here. Correct only if eHAdj == SDRTEXTVERTADJUST_BLOCK, // else the alignment is wanted. if(SDRTEXTVERTADJUST_BLOCK == eVAdj) { eVAdj = SDRTEXTVERTADJUST_CENTER; } } } if (eHAdj==SDRTEXTHORZADJUST_CENTER || eHAdj==SDRTEXTHORZADJUST_RIGHT) { long nFreeWdt=aAnkRect.GetWidth()-aTextSiz.Width(); if (eHAdj==SDRTEXTHORZADJUST_CENTER) aTextPos.X()+=nFreeWdt/2; if (eHAdj==SDRTEXTHORZADJUST_RIGHT) aTextPos.X()+=nFreeWdt; } if (eVAdj==SDRTEXTVERTADJUST_CENTER || eVAdj==SDRTEXTVERTADJUST_BOTTOM) { long nFreeHgt=aAnkRect.GetHeight()-aTextSiz.Height(); if (eVAdj==SDRTEXTVERTADJUST_CENTER) aTextPos.Y()+=nFreeHgt/2; if (eVAdj==SDRTEXTVERTADJUST_BOTTOM) aTextPos.Y()+=nFreeHgt; } if (aGeo.nDrehWink!=0) RotatePoint(aTextPos,aAnkRect.TopLeft(),aGeo.nSin,aGeo.nCos); if (pAnchorRect) *pAnchorRect=aAnkRect; // rTextRect ist bei ContourFrame in einigen Faellen nicht korrekt rTextRect=Rectangle(aTextPos,aTextSiz); if (bContourFrame) rTextRect=aAnkRect; } OutlinerParaObject* SdrTextObj::GetEditOutlinerParaObject() const { OutlinerParaObject* pPara=NULL; if( HasTextImpl( pEdtOutl ) ) { sal_uInt16 nParaAnz = static_cast< sal_uInt16 >( pEdtOutl->GetParagraphCount() ); pPara = pEdtOutl->CreateParaObject(0, nParaAnz); } return pPara; } void SdrTextObj::ImpSetCharStretching(SdrOutliner& rOutliner, const Rectangle& rTextRect, const Rectangle& rAnchorRect, Fraction& rFitXKorreg) const { OutputDevice* pOut = rOutliner.GetRefDevice(); BOOL bNoStretching(FALSE); if(pOut && pOut->GetOutDevType() == OUTDEV_PRINTER) { // #35762#: Checken ob CharStretching ueberhaupt moeglich GDIMetaFile* pMtf = pOut->GetConnectMetaFile(); UniString aTestString(sal_Unicode('J')); if(pMtf && (!pMtf->IsRecord() || pMtf->IsPause())) pMtf = NULL; if(pMtf) pMtf->Pause(TRUE); Font aFontMerk(pOut->GetFont()); Font aTmpFont( OutputDevice::GetDefaultFont( DEFAULTFONT_SERIF, LANGUAGE_SYSTEM, DEFAULTFONT_FLAGS_ONLYONE ) ); aTmpFont.SetSize(Size(0,100)); pOut->SetFont(aTmpFont); Size aSize1(pOut->GetTextWidth(aTestString), pOut->GetTextHeight()); aTmpFont.SetSize(Size(800,100)); pOut->SetFont(aTmpFont); Size aSize2(pOut->GetTextWidth(aTestString), pOut->GetTextHeight()); pOut->SetFont(aFontMerk); if(pMtf) pMtf->Pause(FALSE); bNoStretching = (aSize1 == aSize2); #ifdef WNT // #35762# Windows vergroessert bei Size(100,500) den Font proportional // Und das finden wir nicht so schoen. if(aSize2.Height() >= aSize1.Height() * 2) { bNoStretching = TRUE; } #endif } unsigned nLoopCount=0; FASTBOOL bNoMoreLoop=FALSE; long nXDiff0=0x7FFFFFFF; long nWantWdt=rAnchorRect.Right()-rAnchorRect.Left(); long nIsWdt=rTextRect.Right()-rTextRect.Left(); if (nIsWdt==0) nIsWdt=1; long nWantHgt=rAnchorRect.Bottom()-rAnchorRect.Top(); long nIsHgt=rTextRect.Bottom()-rTextRect.Top(); if (nIsHgt==0) nIsHgt=1; long nXTolPl=nWantWdt/100; // Toleranz +1% long nXTolMi=nWantWdt/25; // Toleranz -4% long nXKorr =nWantWdt/20; // Korrekturmasstab 5% long nX=(nWantWdt*100) /nIsWdt; // X-Stretching berechnen long nY=(nWantHgt*100) /nIsHgt; // Y-Stretching berechnen FASTBOOL bChkX=TRUE; FASTBOOL bChkY=TRUE; if (bNoStretching) { // #35762# evtl. nur proportional moeglich if (nX>nY) { nX=nY; bChkX=FALSE; } else { nY=nX; bChkY=FALSE; } } while (nLoopCount<5 && !bNoMoreLoop) { if (nX<0) nX=-nX; if (nX<1) { nX=1; bNoMoreLoop=TRUE; } if (nX>65535) { nX=65535; bNoMoreLoop=TRUE; } if (nY<0) nY=-nY; if (nY<1) { nY=1; bNoMoreLoop=TRUE; } if (nY>65535) { nY=65535; bNoMoreLoop=TRUE; } // exception, there is no text yet (horizontal case) if(nIsWdt <= 1) { nX = nY; bNoMoreLoop = TRUE; } // #87877# exception, there is no text yet (vertical case) if(nIsHgt <= 1) { nY = nX; bNoMoreLoop = TRUE; } rOutliner.SetGlobalCharStretching((USHORT)nX,(USHORT)nY); nLoopCount++; Size aSiz(rOutliner.CalcTextSize()); long nXDiff=aSiz.Width()-nWantWdt; rFitXKorreg=Fraction(nWantWdt,aSiz.Width()); if (((nXDiff>=nXTolMi || !bChkX) && nXDiff<=nXTolPl) || nXDiff==nXDiff0/*&& Abs(nYDiff)<=nYTol*/) { bNoMoreLoop=TRUE; } else { // Stretchingfaktoren korregieren long nMul=nWantWdt; long nDiv=aSiz.Width(); if (Abs(nXDiff)<=2*nXKorr) { if (nMul>nDiv) nDiv+=(nMul-nDiv)/2; // und zwar nur um die haelfte des berechneten else nMul+=(nDiv-nMul)/2; // weil die EE ja eh wieder falsch rechnet } nX=nX*nMul/nDiv; if (bNoStretching) nY=nX; } nXDiff0=nXDiff; } } sal_Bool SdrTextObj::DoPaintObject(XOutputDevice& rXOut, const SdrPaintInfoRec& rInfoRec) const { sal_Bool bOk(sal_True); FASTBOOL bPrinter=rXOut.GetOutDev()->GetOutDevType()==OUTDEV_PRINTER; FASTBOOL bPrintPreView=rXOut.GetOutDev()->GetOutDevViewType()==OUTDEV_VIEWTYPE_PRINTPREVIEW; // #111096# // allow to hide text if(GetTextHidden()) { return bOk; } // #111096# if(rInfoRec.mbUseBitmapEx) { OutputDevice* pOutDev = rXOut.GetOutDev(); Point aDestPos = pOutDev->LogicToPixel(rInfoRec.maPosition); sal_Bool bMapModeWasEnabledDest(pOutDev->IsMapModeEnabled()); pOutDev->EnableMapMode(sal_False); pOutDev->DrawBitmapEx(aDestPos, rInfoRec.maBitmapEx); pOutDev->EnableMapMode(bMapModeWasEnabledDest); return bOk; } if (bPrinter && bEmptyPresObj) return bOk; // Leere Praesentationsobjekte nicht drucken! if (!bPrinter && pEdtOutl!=NULL && rInfoRec.pPV!=NULL && rInfoRec.pPV->GetView().GetTextEditObject()==(SdrObject*)this) return bOk; // Textobjekt wird gerade editiert in der auffordernen View if(GetOutlinerParaObject()!=NULL || (pEdtOutl!=NULL && HasEditText())) { SdrOutliner& rOutliner=ImpGetDrawOutliner(); { SvtAccessibilityOptions aOptions; bool bForceAutoColor = aOptions.GetIsAutomaticFontColor(); //#106611# don't use automatic colors in WYSIWYG Print Previews if(bPrintPreView&& !aOptions.GetIsForPagePreviews()) bForceAutoColor = false; rOutliner.ForceAutoColor( bForceAutoColor ); } FASTBOOL bContourFrame=IsContourTextFrame(); if (IsFontwork() && !bContourFrame) { // FontWork if (pModel!=NULL) { rOutliner.SetUpdateMode(TRUE); // hier kann ggf. noch optimiert werden !!! ImpTextPortionHandler aTPHandler(rOutliner,*this); // #78478# to have the outline color in XOutputDevice::ImpDrawFormText(...) // SetLineAttr(...) needs to be called if the outline item is set const SfxItemSet& rSet = GetObjectItemSet(); BOOL bFormTextOutline = ((XFormTextOutlineItem&)(rSet.Get(XATTR_FORMTXTOUTLINE))).GetValue(); if(bFormTextOutline) rXOut.SetLineAttr(rSet); rXOut.SetTextAttr(rSet); aTPHandler.DrawTextToPath(rXOut); // drucken bei aktivem Textedit fehlt hier rOutliner.Clear(); } } else if(SDRPAINTMODE_CONTOUR & rInfoRec.nPaintMode) { //#i80528# to not run i a recursion in TakeContour, do not setup an outliner but just // use a polygon paint; the paint is executed to get a contour of the object anyways FASTBOOL bFill=HasFill(); FASTBOOL bLine=HasLine(); FASTBOOL bHide=IsFontwork() && IsHideContour() && pFormTextBoundRect!=NULL; if (bHide) { bFill=FALSE; bLine=FALSE; } if ((bTextFrame && !bLine && !bFill) || bHide) { OutputDevice* pOut=rXOut.GetOutDev(); Polygon aPoly; if (bHide) aPoly=Polygon(*pFormTextBoundRect); else aPoly=Rect2Poly(aRect,aGeo); if (aPoly.GetSize()>=4) { pOut->SetLineColor(Color(COL_BLACK)); pOut->DrawPolyLine(aPoly); pOut->DrawLine(aPoly[0],aPoly[2]); pOut->DrawLine(aPoly[1],aPoly[3]); } } } else { // sonst kein Fontwork // hier findet das richtige Painten des Textes statt Rectangle aTextRect; Rectangle aAnchorRect; Rectangle aPaintRect; Fraction aFitXKorreg(1,1); // the outliner needs the paint info so that CalcFieldValueHdl knows the context for // calculating field values rOutliner.SetPaintInfoRec( &rInfoRec ); // #101029#: Extracted Outliner setup to ImpSetupDrawOutlinerForPaint ImpSetupDrawOutlinerForPaint( bContourFrame, rOutliner, aTextRect, aAnchorRect, aPaintRect, aFitXKorreg ); OutputDevice* pOutDev=rXOut.GetOutDev(); GDIMetaFile* pMtf = pOutDev->GetConnectMetaFile(); // #110496# Apply verbose mode to outliner BOOL bOldVerboseState( rOutliner.IsVerboseTextComments() ); BOOL bWritePaintEndComment( FALSE ); if( rInfoRec.nPaintMode & SDRPAINTMODE_VERBOSE_MTF ) { rOutliner.EnableVerboseTextComments(TRUE); if( pMtf != NULL ) { // #110496# Added some more optional metafile comments. pMtf->AddAction( new MetaCommentAction( "XTEXT_PAINTSHAPE_BEGIN" ) ); bWritePaintEndComment = TRUE; } } if (aGeo.nDrehWink!=0) { // #49328# bei AutoGrowHeight()=TRUE nicht mehr clippen FASTBOOL bNeedClip=(bTextFrame && !IsAutoGrowHeight()) || bContourFrame; // ClipRegion setzen. Das macht Malte bei gedrehter Ausgabe naemlich nicht! FASTBOOL bMtf=pOutDev->GetConnectMetaFile()!=NULL; // Clipping merken FASTBOOL bClip0=pOutDev->IsClipRegion(); Region aClip0(pOutDev->GetClipRegion()); if (bNeedClip) { if (bMtf) pOutDev->Push(); // Neues Clipping setzen Rectangle aClipRect(aPaintRect); if (bPrinter) { // #42520#: Bei HP-Druckern fehlt sonst oefter der letzte Buchstabe einer Zeile Size a1Pix(pOutDev->PixelToLogic(Size(1,1))); aClipRect.Top()-=a1Pix.Width(); aClipRect.Left()-=a1Pix.Height(); aClipRect.Right()+=a1Pix.Width(); aClipRect.Bottom()+=a1Pix.Height(); } Polygon aClipPoly(aClipRect); RotatePoly(aClipPoly,aPaintRect.TopLeft(),aGeo.nSin,aGeo.nCos); // Intersect geht leider nicht, weil Poly statt Rect pOutDev->SetClipRegion(aClipPoly); if (bClip0) { // Aber wenn's vorher nur ein Rechteck war, dann // intersecte ich mein Poly nun mit diesem pOutDev->IntersectClipRegion(aClip0.GetBoundRect()); } } // Textausgabe rOutliner.Draw(pOutDev,aPaintRect.TopLeft(),(short)(aGeo.nDrehWink/10)); if (bNeedClip) { // Clipping restaurieren if (bMtf) pOutDev->Pop(); else { if (bClip0) pOutDev->SetClipRegion(aClip0); else pOutDev->SetClipRegion(); } } } else { if(IsVerticalWriting()) { // new try for #82826# if(aAnchorRect.GetWidth() > aPaintRect.GetWidth()) { aPaintRect = Rectangle( aPaintRect.Right() - aAnchorRect.GetWidth(), aPaintRect.Top(), aPaintRect.Right(), aPaintRect.Bottom()); } // #91744# for vertical writing the original fix #82826# // needs to be taken out. rOutliner.Draw(pOutDev, aPaintRect); } else { // new try for #82826# if(aAnchorRect.GetHeight() > aPaintRect.GetHeight()) { aPaintRect = Rectangle( aPaintRect.Left(), aPaintRect.Top(), aPaintRect.Right(), aPaintRect.Top() + aAnchorRect.GetHeight()); } // #91809# for horizontal writing the original fix #82826# // needs to be taken out, too. rOutliner.Draw(pOutDev, aPaintRect); // #82826# for correct preview of outliner views //// rOutliner.Draw(pOutDev,aPaintRect); //if(aPaintRect.Top() > aAnchorRect.Top()) // rOutliner.Draw(pOutDev, aPaintRect); //else // rOutliner.Draw(pOutDev, aAnchorRect); } } // #110496# Added some more optional metafile comments. if( bWritePaintEndComment ) pMtf->AddAction( new MetaCommentAction( "XTEXT_PAINTSHAPE_END" ) ); // #110496# Restore previous value rOutliner.EnableVerboseTextComments( bOldVerboseState ); rOutliner.Clear(); rOutliner.ClearPaintInfoRec(); } } return bOk; } // Geht z.Zt. nur wenn das Obj schon wenigstens einmal gepaintet wurde // Denn dann ist der MtfAnimator initiallisiert void SdrTextObj::StartTextAnimation(OutputDevice* /*pOutDev*/, const Point& /*rOffset*/, long /*nExtraData*/) { // #111096# // use new text animation SetTextAnimationAllowed(sal_True); } void SdrTextObj::StopTextAnimation(OutputDevice* /*pOutDev*/, long /*nExtraData*/) { // #111096# // use new text animation SetTextAnimationAllowed(sal_False); } void SdrTextObj::RecalcBoundRect() { aOutRect=GetSnapRect(); } void SdrTextObj::ImpAddTextToBoundRect() { if(GetOutlinerParaObject()!=NULL) { if (IsContourTextFrame()) return; if (IsFontwork()) { if (pModel!=NULL) { VirtualDevice aVD; XOutputDevice aXOut(&aVD); SdrOutliner& rOutl=ImpGetDrawOutliner(); rOutl.SetUpdateMode(TRUE); ImpTextPortionHandler aTPHandler(rOutl,*this); aXOut.SetTextAttr(GetObjectItemSet()); aTPHandler.DrawTextToPath(aXOut,FALSE); if (pFormTextBoundRect==NULL) pFormTextBoundRect=new Rectangle; *pFormTextBoundRect=aTPHandler.GetFormTextBoundRect(); aOutRect.Union(*pFormTextBoundRect); } } else { // Ansonsten Text im Zeichenobjekt zentriert if (pFormTextBoundRect!=NULL) { delete pFormTextBoundRect; pFormTextBoundRect=NULL; } FASTBOOL bCheckText=TRUE; if (bTextFrame) { bCheckText=GetTextLeftDistance ()<0 || GetTextRightDistance()<0 || GetTextUpperDistance()<0 || GetTextLowerDistance()<0 || (GetEckenradius()>0 && aGeo.nDrehWink!=0); } if (bCheckText) { SdrOutliner& rOutliner=ImpGetDrawOutliner(); Rectangle aTextRect; Rectangle aAnchorRect; TakeTextRect(rOutliner,aTextRect,TRUE,&aAnchorRect); // EditText ignorieren! SdrFitToSizeType eFit=GetFitToSize(); FASTBOOL bFitToSize=(eFit==SDRTEXTFIT_PROPORTIONAL || eFit==SDRTEXTFIT_ALLLINES); if (bFitToSize) aTextRect=aAnchorRect; rOutliner.Clear(); if (aGeo.nDrehWink!=0) { Polygon aPol(aTextRect); if (aGeo.nDrehWink!=0) RotatePoly(aPol,aTextRect.TopLeft(),aGeo.nSin,aGeo.nCos); aOutRect.Union(aPol.GetBoundRect()); } else { aOutRect.Union(aTextRect); } } } } } SdrObject* SdrTextObj::CheckHit(const Point& rPnt, USHORT nTol, const SetOfByte* pVisiLayer) const { if(!bTextFrame && !GetOutlinerParaObject() ) { return NULL; } if(pVisiLayer && !pVisiLayer->IsSet(sal::static_int_cast< sal_uInt8 >(GetLayer()))) { return NULL; } INT32 nMyTol=nTol; FASTBOOL bFontwork=IsFontwork(); SdrFitToSizeType eFit=GetFitToSize(); FASTBOOL bFitToSize=(eFit==SDRTEXTFIT_PROPORTIONAL || eFit==SDRTEXTFIT_ALLLINES); Rectangle aR(aRect); Rectangle aAnchor2(aR); Rectangle aTextRect(aR); SdrOutliner* pOutliner = NULL; pOutliner = &pModel->GetHitTestOutliner(); if (bFontwork) { if (pFormTextBoundRect!=NULL) aR=*pFormTextBoundRect; else aR=GetCurrentBoundRect(); } else { TakeTextRect( *pOutliner, aTextRect, FALSE, &aAnchor2, FALSE ); // EditText nicht mehr ignorieren! TRUE); // EditText ignorieren! if (bFitToSize) aR=aAnchor2; else aR=aTextRect; } if (aR.GetWidth()-1>short(nTol) && aR.GetHeight()-1>short(nTol)) nMyTol=0; // Keine Toleranz noetig hier if (nMyTol!=0) { aR.Left ()-=nMyTol; aR.Top ()-=nMyTol; aR.Right ()+=nMyTol; aR.Bottom()+=nMyTol; } FASTBOOL bRet=FALSE; if(bFontwork) { bRet = aR.IsInside(rPnt); // #105130# Include aRect here in measurements to be able to hit a // fontwork object on its border if(!bRet) { const Rectangle aSnapRect = GetSnapRect(); if( (rPnt.X() >= aSnapRect.Left() - nTol && rPnt.X() <= aSnapRect.Left() + nTol) || (rPnt.X() >= aSnapRect.Right() - nTol && rPnt.X() <= aSnapRect.Right() + nTol) || (rPnt.Y() >= aSnapRect.Top() - nTol && rPnt.Y() <= aSnapRect.Top() + nTol) || (rPnt.Y() >= aSnapRect.Bottom() - nTol && rPnt.Y() <= aSnapRect.Bottom() + nTol)) { bRet = TRUE; } } } else { if (aGeo.nDrehWink!=0) { Polygon aPol(aR); RotatePoly(aPol,aR.TopLeft(),aGeo.nSin,aGeo.nCos); bRet=IsPointInsidePoly(aPol,rPnt); } else { bRet=aR.IsInside(rPnt); } if (bRet) { // und nun noch checken, ob wirklich Buchstaben getroffen sind // Featurewunsch zur 4.0 // Zunaechst meine Dok-Koordinaten in EE-Dok-Koordinaten umwandeln. Point aPt(rPnt); aPt-=aR.TopLeft(); if (bFitToSize) { // #38214#: FitToSize berueksichtigen Fraction aX(aTextRect.GetWidth()-1,aAnchor2.GetWidth()-1); Fraction aY(aTextRect.GetHeight()-1,aAnchor2.GetHeight()-1); ResizePoint(aPt,Point(),aX,aY); } if (aGeo.nDrehWink!=0) RotatePoint(aPt,Point(),-aGeo.nSin,aGeo.nCos); // -sin fuer Unrotate // Und nun im EE-Dok auf Buchstabensuche gehen long nHitTol = 2000; OutputDevice* pRef = pOutliner->GetRefDevice(); if( pRef ) nHitTol = pRef->LogicToLogic( nHitTol, MAP_100TH_MM, pRef->GetMapMode().GetMapUnit() ); bRet = pOutliner->IsTextPos( aPt, (sal_uInt16)nHitTol ); } } return bRet ? (SdrObject*)this : NULL; } void SdrTextObj::TakeObjNameSingul(XubString& rName) const { XubString aStr; switch(eTextKind) { case OBJ_OUTLINETEXT: { aStr = ImpGetResStr(STR_ObjNameSingulOUTLINETEXT); break; } case OBJ_TITLETEXT : { aStr = ImpGetResStr(STR_ObjNameSingulTITLETEXT); break; } default: { if(IsLinkedText()) aStr = ImpGetResStr(STR_ObjNameSingulTEXTLNK); else aStr = ImpGetResStr(STR_ObjNameSingulTEXT); break; } } OutlinerParaObject* pOutlinerParaObject = GetOutlinerParaObject(); if(pOutlinerParaObject && eTextKind != OBJ_OUTLINETEXT) { // Macht bei OUTLINETEXT wohl derzeit noch etwas Probleme XubString aStr2(pOutlinerParaObject->GetTextObject().GetText(0)); aStr2.EraseLeadingChars(); // #69446# avoid non expanded text portions in object name // (second condition is new) if(aStr2.Len() && aStr2.Search(sal_Unicode(255)) == STRING_NOTFOUND) { // #76681# space between ResStr and content text aStr += sal_Unicode(' '); aStr += sal_Unicode('\''); if(aStr2.Len() > 10) { aStr2.Erase(8); aStr2.AppendAscii("...", 3); } aStr += aStr2; aStr += sal_Unicode('\''); } } rName = aStr; String aName( GetName() ); if(aName.Len()) { rName += sal_Unicode(' '); rName += sal_Unicode('\''); rName += aName; rName += sal_Unicode('\''); } } void SdrTextObj::TakeObjNamePlural(XubString& rName) const { switch (eTextKind) { case OBJ_OUTLINETEXT: rName=ImpGetResStr(STR_ObjNamePluralOUTLINETEXT); break; case OBJ_TITLETEXT : rName=ImpGetResStr(STR_ObjNamePluralTITLETEXT); break; default: { if (IsLinkedText()) { rName=ImpGetResStr(STR_ObjNamePluralTEXTLNK); } else { rName=ImpGetResStr(STR_ObjNamePluralTEXT); } } break; } // switch } void SdrTextObj::operator=(const SdrObject& rObj) { // call parent SdrObject::operator=(rObj); const SdrTextObj* pTextObj = dynamic_cast< const SdrTextObj* >( &rObj ); if (pTextObj!=NULL) { aRect =pTextObj->aRect; aGeo =pTextObj->aGeo; eTextKind =pTextObj->eTextKind; bTextFrame=pTextObj->bTextFrame; aTextSize=pTextObj->aTextSize; bTextSizeDirty=pTextObj->bTextSizeDirty; // #101776# Not all of the necessary parameters were copied yet. bNoShear = pTextObj->bNoShear; bNoRotate = pTextObj->bNoRotate; bNoMirror = pTextObj->bNoMirror; bDisableAutoWidthOnDragging = pTextObj->bDisableAutoWidthOnDragging; OutlinerParaObject* pNewOutlinerParaObject = 0; SdrText* pText = getActiveText(); if( pText && pTextObj->HasText() ) { const Outliner* pEO=pTextObj->pEdtOutl; if (pEO!=NULL) { pNewOutlinerParaObject = pEO->CreateParaObject(); } else { pNewOutlinerParaObject = pTextObj->getActiveText()->GetOutlinerParaObject()->Clone(); } } mpText->SetOutlinerParaObject( pNewOutlinerParaObject ); ImpSetTextStyleSheetListeners(); } } basegfx::B2DPolyPolygon SdrTextObj::TakeXorPoly(sal_Bool /*bDetail*/) const { Polygon aPol(aRect); if (aGeo.nShearWink!=0) ShearPoly(aPol,aRect.TopLeft(),aGeo.nTan); if (aGeo.nDrehWink!=0) RotatePoly(aPol,aRect.TopLeft(),aGeo.nSin,aGeo.nCos); basegfx::B2DPolyPolygon aRetval; aRetval.append(aPol.getB2DPolygon()); return aRetval; } basegfx::B2DPolyPolygon SdrTextObj::TakeContour() const { basegfx::B2DPolyPolygon aRetval(SdrAttrObj::TakeContour()); // und nun noch ggf. das BoundRect des Textes dazu if ( pModel && GetOutlinerParaObject() && !IsFontwork() && !IsContourTextFrame() ) { // #80328# using Clone()-Paint() strategy inside TakeContour() leaves a destroyed // SdrObject as pointer in DrawOutliner. Set *this again in fetching the outliner // in every case SdrOutliner& rOutliner=ImpGetDrawOutliner(); Rectangle aAnchor2; Rectangle aR; TakeTextRect(rOutliner,aR,FALSE,&aAnchor2); rOutliner.Clear(); SdrFitToSizeType eFit=GetFitToSize(); FASTBOOL bFitToSize=(eFit==SDRTEXTFIT_PROPORTIONAL || eFit==SDRTEXTFIT_ALLLINES); if (bFitToSize) aR=aAnchor2; Polygon aPol(aR); if (aGeo.nDrehWink!=0) RotatePoly(aPol,aR.TopLeft(),aGeo.nSin,aGeo.nCos); aRetval.append(aPol.getB2DPolygon()); } return aRetval; } void SdrTextObj::RecalcSnapRect() { if (aGeo.nDrehWink!=0 || aGeo.nShearWink!=0) { Polygon aPol(aRect); if (aGeo.nShearWink!=0) ShearPoly(aPol,aRect.TopLeft(),aGeo.nTan); if (aGeo.nDrehWink!=0) RotatePoly(aPol,aRect.TopLeft(),aGeo.nSin,aGeo.nCos); maSnapRect=aPol.GetBoundRect(); } else { maSnapRect=aRect; } } sal_uInt32 SdrTextObj::GetSnapPointCount() const { return 4L; } Point SdrTextObj::GetSnapPoint(sal_uInt32 i) const { Point aP; switch (i) { case 0: aP=aRect.TopLeft(); break; case 1: aP=aRect.TopRight(); break; case 2: aP=aRect.BottomLeft(); break; case 3: aP=aRect.BottomRight(); break; default: aP=aRect.Center(); break; } if (aGeo.nShearWink!=0) ShearPoint(aP,aRect.TopLeft(),aGeo.nTan); if (aGeo.nDrehWink!=0) RotatePoint(aP,aRect.TopLeft(),aGeo.nSin,aGeo.nCos); return aP; } void SdrTextObj::ImpCheckMasterCachable() { bNotMasterCachable=FALSE; OutlinerParaObject* pOutlinerParaObject = GetOutlinerParaObject(); if(!bNotVisibleAsMaster && pOutlinerParaObject && pOutlinerParaObject->IsEditDoc() ) { const EditTextObject& rText= pOutlinerParaObject->GetTextObject(); bNotMasterCachable=rText.HasField(SvxPageField::StaticType()); if( !bNotMasterCachable ) { bNotMasterCachable=rText.HasField(SvxHeaderField::StaticType()); if( !bNotMasterCachable ) { bNotMasterCachable=rText.HasField(SvxFooterField::StaticType()); if( !bNotMasterCachable ) { bNotMasterCachable=rText.HasField(SvxDateTimeField::StaticType()); } } } } } // #101029#: Extracted from ImpGetDrawOutliner() void SdrTextObj::ImpInitDrawOutliner( SdrOutliner& rOutl ) const { rOutl.SetUpdateMode(FALSE); USHORT nOutlinerMode = OUTLINERMODE_OUTLINEOBJECT; if ( !IsOutlText() ) nOutlinerMode = OUTLINERMODE_TEXTOBJECT; rOutl.Init( nOutlinerMode ); rOutl.SetGlobalCharStretching(100,100); ULONG nStat=rOutl.GetControlWord(); nStat&=~(EE_CNTRL_STRETCHING|EE_CNTRL_AUTOPAGESIZE); rOutl.SetControlWord(nStat); Size aNullSize; Size aMaxSize(100000,100000); rOutl.SetMinAutoPaperSize(aNullSize); rOutl.SetMaxAutoPaperSize(aMaxSize); rOutl.SetPaperSize(aMaxSize); rOutl.ClearPolygon(); } SdrOutliner& SdrTextObj::ImpGetDrawOutliner() const { SdrOutliner& rOutl=pModel->GetDrawOutliner(this); // #101029#: Code extracted to ImpInitDrawOutliner() ImpInitDrawOutliner( rOutl ); return rOutl; } boost::shared_ptr< SdrOutliner > SdrTextObj::CreateDrawOutliner() { boost::shared_ptr< SdrOutliner > xDrawOutliner( pModel->CreateDrawOutliner(this) ); ImpInitDrawOutliner( *(xDrawOutliner.get()) ); return xDrawOutliner; } // #101029#: Extracted from Paint() void SdrTextObj::ImpSetupDrawOutlinerForPaint( FASTBOOL bContourFrame, SdrOutliner& rOutliner, Rectangle& rTextRect, Rectangle& rAnchorRect, Rectangle& rPaintRect, Fraction& rFitXKorreg ) const { if (!bContourFrame) { // FitToSize erstmal nicht mit ContourFrame SdrFitToSizeType eFit=GetFitToSize(); if (eFit==SDRTEXTFIT_PROPORTIONAL || eFit==SDRTEXTFIT_ALLLINES) { ULONG nStat=rOutliner.GetControlWord(); nStat|=EE_CNTRL_STRETCHING|EE_CNTRL_AUTOPAGESIZE; rOutliner.SetControlWord(nStat); } } rOutliner.SetFixedCellHeight(((const SdrTextFixedCellHeightItem&)GetMergedItem(SDRATTR_TEXT_USEFIXEDCELLHEIGHT)).GetValue()); TakeTextRect(rOutliner, rTextRect, FALSE, &rAnchorRect); rPaintRect = rTextRect; if (!bContourFrame) { // FitToSize erstmal nicht mit ContourFrame SdrFitToSizeType eFit=GetFitToSize(); if (eFit==SDRTEXTFIT_PROPORTIONAL || eFit==SDRTEXTFIT_ALLLINES) { ImpSetCharStretching(rOutliner,rTextRect,rAnchorRect,rFitXKorreg); rPaintRect=rAnchorRect; } } } void SdrTextObj::SetupOutlinerFormatting( SdrOutliner& rOutl, Rectangle& rPaintRect ) const { ImpInitDrawOutliner( rOutl ); UpdateOutlinerFormatting( rOutl, rPaintRect ); } void SdrTextObj::UpdateOutlinerFormatting( SdrOutliner& rOutl, Rectangle& rPaintRect ) const { Rectangle aTextRect; Rectangle aAnchorRect; Fraction aFitXKorreg(1,1); FASTBOOL bContourFrame=IsContourTextFrame(); ImpSetupDrawOutlinerForPaint( bContourFrame, rOutl, aTextRect, aAnchorRect, rPaintRect, aFitXKorreg ); if( GetModel() ) { MapMode aMapMode(GetModel()->GetScaleUnit(), Point(0,0), GetModel()->GetScaleFraction(), GetModel()->GetScaleFraction()); rOutl.SetRefMapMode(aMapMode); } } //////////////////////////////////////////////////////////////////////////////////////////////////// OutlinerParaObject* SdrTextObj::GetOutlinerParaObject() const { SdrText* pText = getActiveText(); if( pText ) return pText->GetOutlinerParaObject(); else return 0; } bool SdrTextObj::HasOutlinerParaObject() const { SdrText* pText = getActiveText(); if( pText && pText->GetOutlinerParaObject() ) return true; return false; } void SdrTextObj::NbcSetOutlinerParaObject(OutlinerParaObject* pTextObject) { NbcSetOutlinerParaObjectForText( pTextObject, getActiveText() ); } void SdrTextObj::NbcSetOutlinerParaObjectForText( OutlinerParaObject* pTextObject, SdrText* pText ) { if( pText ) pText->SetOutlinerParaObject( pTextObject ); if( pText->GetOutlinerParaObject() ) { SvxWritingModeItem aWritingMode(pText->GetOutlinerParaObject()->IsVertical() ? com::sun::star::text::WritingMode_TB_RL : com::sun::star::text::WritingMode_LR_TB, SDRATTR_TEXTDIRECTION); GetProperties().SetObjectItemDirect(aWritingMode); } SetTextSizeDirty(); if (IsTextFrame() && (IsAutoGrowHeight() || IsAutoGrowWidth())) { // Textrahmen anpassen! NbcAdjustTextFrameWidthAndHeight(); } if (!IsTextFrame()) { // Das SnapRect behaelt seine Groesse bei bBoundRectDirty=TRUE; SetRectsDirty(sal_True); } ImpSetTextStyleSheetListeners(); ImpCheckMasterCachable(); } void SdrTextObj::NbcReformatText() { SdrText* pText = getActiveText(); if( pText && pText->GetOutlinerParaObject() ) { pText->ReformatText(); if (bTextFrame) { NbcAdjustTextFrameWidthAndHeight(); } else { // Das SnapRect behaelt seine Groesse bei bBoundRectDirty=TRUE; SetRectsDirty(sal_True); } SetTextSizeDirty(); } } void SdrTextObj::ReformatText() { if(GetOutlinerParaObject()) { Rectangle aBoundRect0; if (pUserCall!=NULL) aBoundRect0=GetLastBoundRect(); // #110094#-14 SendRepaintBroadcast(); NbcReformatText(); SetChanged(); BroadcastObjectChange(); SendUserCall(SDRUSERCALL_RESIZE,aBoundRect0); } } SdrObjGeoData* SdrTextObj::NewGeoData() const { return new SdrTextObjGeoData; } void SdrTextObj::SaveGeoData(SdrObjGeoData& rGeo) const { SdrAttrObj::SaveGeoData(rGeo); SdrTextObjGeoData& rTGeo=(SdrTextObjGeoData&)rGeo; rTGeo.aRect =aRect; rTGeo.aGeo =aGeo; } void SdrTextObj::RestGeoData(const SdrObjGeoData& rGeo) { // RectsDirty wird von SdrObject gerufen SdrAttrObj::RestGeoData(rGeo); SdrTextObjGeoData& rTGeo=(SdrTextObjGeoData&)rGeo; aRect =rTGeo.aRect; aGeo =rTGeo.aGeo; SetTextSizeDirty(); } SdrFitToSizeType SdrTextObj::GetFitToSize() const { SdrFitToSizeType eType = SDRTEXTFIT_NONE; if(!IsAutoGrowWidth()) eType = ((SdrTextFitToSizeTypeItem&)(GetObjectItem(SDRATTR_TEXT_FITTOSIZE))).GetValue(); return eType; } void SdrTextObj::ForceOutlinerParaObject() { SdrText* pText = getActiveText(); if( pText && (pText->GetOutlinerParaObject() == 0) ) { USHORT nOutlMode = OUTLINERMODE_TEXTOBJECT; if( IsTextFrame() && eTextKind == OBJ_OUTLINETEXT ) nOutlMode = OUTLINERMODE_OUTLINEOBJECT; pText->ForceOutlinerParaObject( nOutlMode ); } } sal_Bool SdrTextObj::IsVerticalWriting() const { // #89459# if(pEdtOutl) { return pEdtOutl->IsVertical(); } OutlinerParaObject* pOutlinerParaObject = GetOutlinerParaObject(); if(pOutlinerParaObject) { return pOutlinerParaObject->IsVertical(); } return sal_False; } void SdrTextObj::SetVerticalWriting(sal_Bool bVertical) { OutlinerParaObject* pOutlinerParaObject = GetOutlinerParaObject(); if( pOutlinerParaObject ) { if( !pOutlinerParaObject && bVertical ) { // we only need to force a outliner para object if the default of // horizontal text is changed ForceOutlinerParaObject(); pOutlinerParaObject = GetOutlinerParaObject(); } if( pOutlinerParaObject && (pOutlinerParaObject->IsVertical() != bVertical) ) { // get item settings const SfxItemSet& rSet = GetObjectItemSet(); sal_Bool bAutoGrowWidth = ((SdrTextAutoGrowWidthItem&)rSet.Get(SDRATTR_TEXT_AUTOGROWWIDTH)).GetValue(); sal_Bool bAutoGrowHeight = ((SdrTextAutoGrowHeightItem&)rSet.Get(SDRATTR_TEXT_AUTOGROWHEIGHT)).GetValue(); // #103516# Also exchange hor/ver adjust items SdrTextHorzAdjust eHorz = ((SdrTextHorzAdjustItem&)(rSet.Get(SDRATTR_TEXT_HORZADJUST))).GetValue(); SdrTextVertAdjust eVert = ((SdrTextVertAdjustItem&)(rSet.Get(SDRATTR_TEXT_VERTADJUST))).GetValue(); // rescue object size Rectangle aObjectRect = GetSnapRect(); // prepare ItemSet to set exchanged width and height items SfxItemSet aNewSet(*rSet.GetPool(), SDRATTR_TEXT_AUTOGROWHEIGHT, SDRATTR_TEXT_AUTOGROWHEIGHT, // #103516# Expanded item ranges to also support hor and ver adjust. SDRATTR_TEXT_VERTADJUST, SDRATTR_TEXT_VERTADJUST, SDRATTR_TEXT_AUTOGROWWIDTH, SDRATTR_TEXT_HORZADJUST, 0, 0); aNewSet.Put(rSet); aNewSet.Put(SdrTextAutoGrowWidthItem(bAutoGrowHeight)); aNewSet.Put(SdrTextAutoGrowHeightItem(bAutoGrowWidth)); // #103516# Exchange horz and vert adjusts switch(eVert) { case SDRTEXTVERTADJUST_TOP: aNewSet.Put(SdrTextHorzAdjustItem(SDRTEXTHORZADJUST_RIGHT)); break; case SDRTEXTVERTADJUST_CENTER: aNewSet.Put(SdrTextHorzAdjustItem(SDRTEXTHORZADJUST_CENTER)); break; case SDRTEXTVERTADJUST_BOTTOM: aNewSet.Put(SdrTextHorzAdjustItem(SDRTEXTHORZADJUST_LEFT)); break; case SDRTEXTVERTADJUST_BLOCK: aNewSet.Put(SdrTextHorzAdjustItem(SDRTEXTHORZADJUST_BLOCK)); break; } switch(eHorz) { case SDRTEXTHORZADJUST_LEFT: aNewSet.Put(SdrTextVertAdjustItem(SDRTEXTVERTADJUST_BOTTOM)); break; case SDRTEXTHORZADJUST_CENTER: aNewSet.Put(SdrTextVertAdjustItem(SDRTEXTVERTADJUST_CENTER)); break; case SDRTEXTHORZADJUST_RIGHT: aNewSet.Put(SdrTextVertAdjustItem(SDRTEXTVERTADJUST_TOP)); break; case SDRTEXTHORZADJUST_BLOCK: aNewSet.Put(SdrTextVertAdjustItem(SDRTEXTVERTADJUST_BLOCK)); break; } SetObjectItemSet(aNewSet); pOutlinerParaObject = GetOutlinerParaObject(); if( pOutlinerParaObject ) { // set ParaObject orientation accordingly pOutlinerParaObject->SetVertical(bVertical); } // restore object size SetSnapRect(aObjectRect); } } } //////////////////////////////////////////////////////////////////////////////////////////////////// // // transformation interface for StarOfficeAPI. This implements support for // homogen 3x3 matrices containing the transformation of the SdrObject. At the // moment it contains a shearX, rotation and translation, but for setting all linear // transforms like Scale, ShearX, ShearY, Rotate and Translate are supported. // //////////////////////////////////////////////////////////////////////////////////////////////////// // gets base transformation and rectangle of object. If it's an SdrPathObj it fills the PolyPolygon // with the base geometry and returns TRUE. Otherwise it returns FALSE. sal_Bool SdrTextObj::TRGetBaseGeometry(basegfx::B2DHomMatrix& rMatrix, basegfx::B2DPolyPolygon& /*rPolyPolygon*/) const { // get turn and shear double fRotate = (aGeo.nDrehWink / 100.0) * F_PI180; double fShearX = (aGeo.nShearWink / 100.0) * F_PI180; // get aRect, this is the unrotated snaprect Rectangle aRectangle(aRect); // fill other values basegfx::B2DTuple aScale(aRectangle.GetWidth(), aRectangle.GetHeight()); basegfx::B2DTuple aTranslate(aRectangle.Left(), aRectangle.Top()); // position maybe relative to anchorpos, convert if( pModel->IsWriter() ) { if(GetAnchorPos().X() || GetAnchorPos().Y()) { aTranslate -= basegfx::B2DTuple(GetAnchorPos().X(), GetAnchorPos().Y()); } } // force MapUnit to 100th mm SfxMapUnit eMapUnit = pModel->GetItemPool().GetMetric(0); if(eMapUnit != SFX_MAPUNIT_100TH_MM) { switch(eMapUnit) { case SFX_MAPUNIT_TWIP : { // postion aTranslate.setX(ImplTwipsToMM(aTranslate.getX())); aTranslate.setY(ImplTwipsToMM(aTranslate.getY())); // size aScale.setX(ImplTwipsToMM(aScale.getX())); aScale.setY(ImplTwipsToMM(aScale.getY())); break; } default: { DBG_ERROR("TRGetBaseGeometry: Missing unit translation to 100th mm!"); } } } // build matrix rMatrix.identity(); if(!basegfx::fTools::equal(aScale.getX(), 1.0) || !basegfx::fTools::equal(aScale.getY(), 1.0)) { rMatrix.scale(aScale.getX(), aScale.getY()); } if(!basegfx::fTools::equalZero(fShearX)) { rMatrix.shearX(tan(fShearX)); } if(!basegfx::fTools::equalZero(fRotate)) { // #i78696# // fRotate is from the old GeoStat and thus mathematically wrong orientated. For // the linear combination of matrices it needed to be fixed in the API, so it needs to // be mirrored here rMatrix.rotate(-fRotate); } if(!aTranslate.equalZero()) { rMatrix.translate(aTranslate.getX(), aTranslate.getY()); } return sal_False; } // sets the base geometry of the object using infos contained in the homogen 3x3 matrix. // If it's an SdrPathObj it will use the provided geometry information. The Polygon has // to use (0,0) as upper left and will be scaled to the given size in the matrix. void SdrTextObj::TRSetBaseGeometry(const basegfx::B2DHomMatrix& rMatrix, const basegfx::B2DPolyPolygon& /*rPolyPolygon*/) { // break up matrix basegfx::B2DTuple aScale; basegfx::B2DTuple aTranslate; double fRotate, fShearX; rMatrix.decompose(aScale, aTranslate, fRotate, fShearX); // #i75086# Old DrawingLayer (GeoStat and geometry) does not support holding negative scalings // in X and Y which equal a 180 degree rotation. Recognize it and react accordingly if(basegfx::fTools::less(aScale.getX(), 0.0) && basegfx::fTools::less(aScale.getY(), 0.0)) { aScale.setX(fabs(aScale.getX())); aScale.setY(fabs(aScale.getY())); fRotate = fmod(fRotate + F_PI, F_2PI); } // reset object shear and rotations aGeo.nDrehWink = 0; aGeo.RecalcSinCos(); aGeo.nShearWink = 0; aGeo.RecalcTan(); // force metric to pool metric SfxMapUnit eMapUnit = pModel->GetItemPool().GetMetric(0); if(eMapUnit != SFX_MAPUNIT_100TH_MM) { switch(eMapUnit) { case SFX_MAPUNIT_TWIP : { // position aTranslate.setX(ImplMMToTwips(aTranslate.getX())); aTranslate.setY(ImplMMToTwips(aTranslate.getY())); // size aScale.setX(ImplMMToTwips(aScale.getX())); aScale.setY(ImplMMToTwips(aScale.getY())); break; } default: { DBG_ERROR("TRSetBaseGeometry: Missing unit translation to PoolMetric!"); } } } // if anchor is used, make position relative to it if( pModel->IsWriter() ) { if(GetAnchorPos().X() || GetAnchorPos().Y()) { aTranslate += basegfx::B2DTuple(GetAnchorPos().X(), GetAnchorPos().Y()); } } // build and set BaseRect (use scale) Point aPoint = Point(); Size aSize(FRound(aScale.getX()), FRound(aScale.getY())); Rectangle aBaseRect(aPoint, aSize); SetSnapRect(aBaseRect); // shear? if(!basegfx::fTools::equalZero(fShearX)) { GeoStat aGeoStat; aGeoStat.nShearWink = FRound((atan(fShearX) / F_PI180) * 100.0); aGeoStat.RecalcTan(); Shear(Point(), aGeoStat.nShearWink, aGeoStat.nTan, FALSE); } // rotation? if(!basegfx::fTools::equalZero(fRotate)) { GeoStat aGeoStat; // #i78696# // fRotate is matematically correct, but aGeoStat.nDrehWink is // mirrored -> mirror value here aGeoStat.nDrehWink = NormAngle360(FRound(-fRotate / F_PI18000)); aGeoStat.RecalcSinCos(); Rotate(Point(), aGeoStat.nDrehWink, aGeoStat.nSin, aGeoStat.nCos); } // translate? if(!aTranslate.equalZero()) { Move(Size(FRound(aTranslate.getX()), FRound(aTranslate.getY()))); } } bool SdrTextObj::IsRealyEdited() const { return pEdtOutl && pEdtOutl->IsModified(); } ///////////////////////////////////////////////////////////////////////////////////////////////// // moved inlines here form hxx long SdrTextObj::GetEckenradius() const { return ((SdrEckenradiusItem&)(GetObjectItemSet().Get(SDRATTR_ECKENRADIUS))).GetValue(); } long SdrTextObj::GetMinTextFrameHeight() const { return ((SdrTextMinFrameHeightItem&)(GetObjectItemSet().Get(SDRATTR_TEXT_MINFRAMEHEIGHT))).GetValue(); } long SdrTextObj::GetMaxTextFrameHeight() const { return ((SdrTextMaxFrameHeightItem&)(GetObjectItemSet().Get(SDRATTR_TEXT_MAXFRAMEHEIGHT))).GetValue(); } long SdrTextObj::GetMinTextFrameWidth() const { return ((SdrTextMinFrameWidthItem&)(GetObjectItemSet().Get(SDRATTR_TEXT_MINFRAMEWIDTH))).GetValue(); } long SdrTextObj::GetMaxTextFrameWidth() const { return ((SdrTextMaxFrameWidthItem&)(GetObjectItemSet().Get(SDRATTR_TEXT_MAXFRAMEWIDTH))).GetValue(); } FASTBOOL SdrTextObj::IsFontwork() const { return (bTextFrame) ? FALSE // Default ist FALSE : ((XFormTextStyleItem&)(GetObjectItemSet().Get(XATTR_FORMTXTSTYLE))).GetValue()!=XFT_NONE; } FASTBOOL SdrTextObj::IsHideContour() const { return (bTextFrame) ? FALSE // Default ist: Nein, kein HideContour; HideContour nicht bei TextFrames : ((XFormTextHideFormItem&)(GetObjectItemSet().Get(XATTR_FORMTXTHIDEFORM))).GetValue(); } FASTBOOL SdrTextObj::IsContourTextFrame() const { return (bTextFrame) ? FALSE // ContourFrame nicht bei normalen TextFrames : ((SdrTextContourFrameItem&)(GetObjectItemSet().Get(SDRATTR_TEXT_CONTOURFRAME))).GetValue(); } long SdrTextObj::GetTextLeftDistance() const { return ((SdrTextLeftDistItem&)(GetObjectItemSet().Get(SDRATTR_TEXT_LEFTDIST))).GetValue(); } long SdrTextObj::GetTextRightDistance() const { return ((SdrTextRightDistItem&)(GetObjectItemSet().Get(SDRATTR_TEXT_RIGHTDIST))).GetValue(); } long SdrTextObj::GetTextUpperDistance() const { return ((SdrTextUpperDistItem&)(GetObjectItemSet().Get(SDRATTR_TEXT_UPPERDIST))).GetValue(); } long SdrTextObj::GetTextLowerDistance() const { return ((SdrTextLowerDistItem&)(GetObjectItemSet().Get(SDRATTR_TEXT_LOWERDIST))).GetValue(); } SdrTextAniKind SdrTextObj::GetTextAniKind() const { return ((SdrTextAniKindItem&)(GetObjectItemSet().Get(SDRATTR_TEXT_ANIKIND))).GetValue(); } SdrTextAniDirection SdrTextObj::GetTextAniDirection() const { return ((SdrTextAniDirectionItem&)(GetObjectItemSet().Get(SDRATTR_TEXT_ANIDIRECTION))).GetValue(); } // #111096# // Access to thext hidden flag sal_Bool SdrTextObj::GetTextHidden() const { return mbTextHidden; } void SdrTextObj::NbcSetTextHidden(sal_Bool bNew) { if(bNew != mbTextHidden) { mbTextHidden = bNew; } } // #111096# // Get necessary data for text scroll animation. ATM base it on a Text-Metafile and a // painting rectangle. Rotation is excluded from the returned values. GDIMetaFile* SdrTextObj::GetTextScrollMetaFileAndRectangle( Rectangle& rScrollRectangle, Rectangle& rPaintRectangle) { GDIMetaFile* pRetval = 0L; SdrOutliner& rOutliner = ImpGetDrawOutliner(); Rectangle aTextRect; Rectangle aAnchorRect; Rectangle aPaintRect; Fraction aFitXKorreg(1,1); bool bContourFrame(IsContourTextFrame()); // get outliner set up. To avoid getting a somehow rotated MetaFile, // temporarily disable object rotation. sal_Int32 nAngle(aGeo.nDrehWink); aGeo.nDrehWink = 0L; ImpSetupDrawOutlinerForPaint( bContourFrame, rOutliner, aTextRect, aAnchorRect, aPaintRect, aFitXKorreg ); aGeo.nDrehWink = nAngle; Rectangle aScrollFrameRect(aPaintRect); const SfxItemSet& rSet = GetObjectItemSet(); SdrTextAniDirection eDirection = ((SdrTextAniDirectionItem&)(rSet.Get(SDRATTR_TEXT_ANIDIRECTION))).GetValue(); if(SDRTEXTANI_LEFT == eDirection || SDRTEXTANI_RIGHT == eDirection) { aScrollFrameRect.Left() = aAnchorRect.Left(); aScrollFrameRect.Right() = aAnchorRect.Right(); } if(SDRTEXTANI_UP == eDirection || SDRTEXTANI_DOWN == eDirection) { aScrollFrameRect.Top() = aAnchorRect.Top(); aScrollFrameRect.Bottom() = aAnchorRect.Bottom(); } // create the MetaFile pRetval = new GDIMetaFile; VirtualDevice aBlackHole; aBlackHole.EnableOutput(sal_False); pRetval->Record(&aBlackHole); Point aPaintPos = aPaintRect.TopLeft(); sal_uInt32 nStat0(rOutliner.GetControlWord()); rOutliner.SetControlWord(nStat0|EE_CNTRL_NOREDLINES); rOutliner.Draw(&aBlackHole, aPaintPos); rOutliner.SetControlWord(nStat0); pRetval->Stop(); pRetval->WindStart(); // return PaintRectanglePixel and pRetval; rScrollRectangle = aScrollFrameRect; rPaintRectangle = aPaintRect; return pRetval; } // #111096# // Access to TextAnimationAllowed flag sal_Bool SdrTextObj::IsTextAnimationAllowed() const { return mbTextAnimationAllowed; } void SdrTextObj::SetTextAnimationAllowed(sal_Bool bNew) { if(mbTextAnimationAllowed != bNew) { mbTextAnimationAllowed = bNew; ActionChanged(); } } /** called from the SdrObjEditView during text edit when the status of the edit outliner changes */ void SdrTextObj::onEditOutlinerStatusEvent( EditStatus* pEditStatus ) { const sal_uInt32 nStat = pEditStatus->GetStatusWord(); const bool bGrowX=(nStat & EE_STAT_TEXTWIDTHCHANGED) !=0; const bool bGrowY=(nStat & EE_STAT_TEXTHEIGHTCHANGED) !=0; if(bTextFrame && (bGrowX || bGrowY)) { const bool bAutoGrowHgt= bTextFrame && IsAutoGrowHeight(); const bool bAutoGrowWdt= bTextFrame && IsAutoGrowWidth(); if ((bGrowX && bAutoGrowWdt) || (bGrowY && bAutoGrowHgt)) { AdjustTextFrameWidthAndHeight(); } } } /** returns the currently active text. */ SdrText* SdrTextObj::getActiveText() const { if( !mpText ) return getText( 0 ); else return mpText; } /** returns the nth available text. */ SdrText* SdrTextObj::getText( sal_Int32 nIndex ) const { if( nIndex == 0 ) { if( mpText == 0 ) const_cast< SdrTextObj* >(this)->mpText = new SdrText( const_cast< SdrTextObj* >(this) ); return mpText; } else { return 0; } } /** returns the number of texts available for this object. */ sal_Int32 SdrTextObj::getTextCount() const { return 1; } /** changes the current active text */ void SdrTextObj::setActiveText( sal_Int32 /*nIndex*/ ) { } /** returns the index of the text that contains the given point or -1 */ sal_Int32 SdrTextObj::CheckTextHit(const Point& /*rPnt*/) const { return 0; } ///////////////////////////////////////////////////////////////////////////////////////////////// // // Konzept des TextObjekts: // ~~~~~~~~~~~~~~~~~~~~~~~~ // Attribute/Varianten: // - BOOL Textrahmen / beschriftetes Zeichenobjekt // - BOOL FontWork (wenn nicht Textrahmen und nicht ContourTextFrame) // - BOOL ContourTextFrame (wenn nicht Textrahmen und nicht Fontwork) // - long Drehwinkel (wenn nicht FontWork) // - long Textrahmenabstaende (wenn nicht FontWork) // - BOOL FitToSize (wenn nicht FontWork) // - BOOL AutoGrowingWidth/Height (wenn nicht FitToSize und nicht FontWork) // - long Min/MaxFrameWidth/Height (wenn AutoGrowingWidth/Height) // - enum Horizontale Textverankerung Links,Mitte,Rechts,Block,Stretch(ni) // - enum Vertikale Textverankerung Oben,Mitte,Unten,Block,Stretch(ni) // - enum Laufschrift (wenn nicht FontWork) // // Jedes abgeleitete Objekt ist entweder ein Textrahmen (bTextFrame=TRUE) // oder ein beschriftetes Zeichenobjekt (bTextFrame=FALSE). // // Defaultverankerung von Textrahmen: // SDRTEXTHORZADJUST_BLOCK, SDRTEXTVERTADJUST_TOP // = statische Pooldefaults // Defaultverankerung von beschrifteten Zeichenobjekten: // SDRTEXTHORZADJUST_CENTER, SDRTEXTVERTADJUST_CENTER // durch harte Attributierung von SdrAttrObj // // Jedes vom SdrTextObj abgeleitete Objekt muss ein "UnrotatedSnapRect" // (->TakeUnrotatedSnapRect()) liefern (Drehreferenz ist TopLeft dieses // Rechtecks (aGeo.nDrehWink)), welches die Grundlage der Textverankerung // bildet. Von diesem werden dann ringsum die Textrahmenabstaende abgezogen; // das Ergebnis ist der Ankerbereich (->TakeTextAnchorRect()). Innerhalb // dieses Bereichs wird dann in Abhaengigkeit von der horizontalen und // vertikalen Ausrichtung (SdrTextVertAdjust,SdrTextHorzAdjust) der Ankerpunkt // sowie der Ausgabebereich bestimmt. Bei beschrifteten Grafikobjekten kann // der Ausgabebereich durchaus groesser als der Ankerbereich werden, bei // Textrahmen ist er stets kleiner oder gleich (ausser bei negativen Textrahmen- // abstaenden). // // FitToSize hat Prioritaet vor Textverankerung und AutoGrowHeight/Width. Der // Ausgabebereich ist bei FitToSize immer genau der Ankerbereich. Weiterhin // gibt es bei FitToSize keinen automatischen Zeilenumbruch. // // ContourTextFrame: // - long Drehwinkel // - long Textrahmenabstaende spaeter vielleicht // - BOOL FitToSize spaeter vielleicht // - BOOL AutoGrowingWidth/Height viel spaeter vielleicht // - long Min/MaxFrameWidth/Height viel spaeter vielleicht // - enum Horizontale Textverankerung spaeter vielleicht, erstmal Links, Absatz zentr. // - enum Vertikale Textverankerung spaeter vielleicht, erstmal oben // - enum Laufschrift spaeter vielleicht (evtl. sogar mit korrektem Clipping) // // Bei Aenderungen zu beachten: // - Paint // - HitTest // - RecalcBoundRect // - ConvertToPoly // - Edit // - Drucken,Speichern, Paint in Nachbarview waerend Edit // - ModelChanged (z.B. durch NachbarView oder Lineale) waerend Edit // - FillColorChanged waerend Edit // - uvm... // /////////////////////////////////////////////////////////////////////////////////////////////////