/************************************************************** * * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. * *************************************************************/ // MARKER(update_precomp.py): autogen include statement, do not remove #include "precompiled_svx.hxx" #include #include "svx/svditext.hxx" #include // fuer Abfrage im Paint, ob das #include // Objekt gerade editiert wird #include // und fuer AnimationHandler (Laufschrift) #include #include #include // OutlinerDefaults #include "svx/svdglob.hxx" // Stringcache #include "svx/svdstr.hrc" // Objektname #include #include #include #include #include #include #include #include #include #include #include #include #include #include // FRound #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include ////////////////////////////////////////////////////////////////////////////// using namespace com::sun::star; ////////////////////////////////////////////////////////////////////////////// // #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=sal_False; bTextFrame=sal_False; bNoShear=sal_False; bNoRotate=sal_False; bNoMirror=sal_False; bDisableAutoWidthOnDragging=sal_False; // #101684# mbInEditMode = sal_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=sal_False; bTextFrame=sal_False; bNoShear=sal_False; bNoRotate=sal_False; bNoMirror=sal_False; bDisableAutoWidthOnDragging=sal_False; ImpJustifyRect(aRect); // #101684# mbInEditMode = sal_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=sal_False; bTextFrame=sal_True; bNoShear=sal_True; bNoRotate=sal_False; bNoMirror=sal_True; bDisableAutoWidthOnDragging=sal_False; // #101684# mbInEditMode = sal_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=sal_False; bTextFrame=sal_True; bNoShear=sal_True; bNoRotate=sal_False; bNoMirror=sal_True; bDisableAutoWidthOnDragging=sal_False; ImpJustifyRect(aRect); // #101684# mbInEditMode = sal_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, sal_uInt16 eFormat) : SdrAttrObj(), aRect(rNewRect), mpText(NULL), pEdtOutl(NULL), pFormTextBoundRect(NULL), eTextKind(eNewTextKind) { bTextSizeDirty=sal_False; bTextFrame=sal_True; bNoShear=sal_True; bNoRotate=sal_False; bNoMirror=sal_True; bDisableAutoWidthOnDragging=sal_False; ImpJustifyRect(aRect); NbcSetText(rInput, rBaseURL, eFormat); // #101684# mbInEditMode = sal_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(sal_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(sal_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=sal_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, sal_uInt16 eFormat) { SdrOutliner& rOutliner=ImpGetDrawOutliner(); rOutliner.SetStyleSheet( 0, GetStyleSheet()); rOutliner.Read(rInput,rBaseURL,eFormat); OutlinerParaObject* pNewText=rOutliner.CreateParaObject(); rOutliner.SetUpdateMode(sal_True); Size aSiz(rOutliner.CalcTextSize()); rOutliner.Clear(); NbcSetOutlinerParaObject(pNewText); aTextSize=aSiz; bTextSizeDirty=sal_False; } void SdrTextObj::SetText(SvStream& rInput, const String& rBaseURL, sal_uInt16 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(sal_True); aSiz=rOutliner.CalcTextSize(); rOutliner.Clear(); } // 2x casting auf nonconst ((SdrTextObj*)this)->aTextSize=aSiz; ((SdrTextObj*)this)->bTextSizeDirty=sal_False; } return aTextSize; } FASTBOOL SdrTextObj::IsAutoGrowHeight() const { if(!bTextFrame) return sal_False; // AutoGrow nur bei TextFrames const SfxItemSet& rSet = GetObjectItemSet(); sal_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 = sal_False; } } } return bRet; } FASTBOOL SdrTextObj::IsAutoGrowWidth() const { if(!bTextFrame) return sal_False; // AutoGrow nur bei TextFrames const SfxItemSet& rSet = GetObjectItemSet(); sal_Bool bRet = ((SdrTextAutoGrowHeightItem&)(rSet.Get(SDRATTR_TEXT_AUTOGROWWIDTH))).GetValue(); // #101684# sal_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 = sal_False; } } } return bRet; } SdrTextHorzAdjust SdrTextObj::GetTextHorizontalAdjust() const { return GetTextHorizontalAdjust(GetObjectItemSet()); } SdrTextHorzAdjust SdrTextObj::GetTextHorizontalAdjust(const SfxItemSet& rSet) const { if(IsContourTextFrame()) return SDRTEXTHORZADJUST_BLOCK; SdrTextHorzAdjust eRet = ((SdrTextHorzAdjustItem&)(rSet.Get(SDRATTR_TEXT_HORZADJUST))).GetValue(); // #101684# sal_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 { return GetTextVerticalAdjust(GetObjectItemSet()); } SdrTextVertAdjust SdrTextObj::GetTextVerticalAdjust(const SfxItemSet& rSet) const { if(IsContourTextFrame()) return SDRTEXTVERTADJUST_TOP; // #103516# Take care for vertical text animation here SdrTextVertAdjust eRet = ((SdrTextVertAdjustItem&)(rSet.Get(SDRATTR_TEXT_VERTADJUST))).GetValue(); sal_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=sal_True; rInfo.bRotateFreeAllowed=sal_True; rInfo.bRotate90Allowed =sal_True; rInfo.bMirrorFreeAllowed=bNoTextFrame; rInfo.bMirror45Allowed =bNoTextFrame; rInfo.bMirror90Allowed =bNoTextFrame; // allow transparence rInfo.bTransparenceAllowed = sal_True; // gradient depends on fillstyle XFillStyle eFillStyle = ((XFillStyleItem&)(GetObjectItem(XATTR_FILLSTYLE))).GetValue(); rInfo.bGradientAllowed = (eFillStyle == XFILL_GRADIENT); rInfo.bShearAllowed =bNoTextFrame; rInfo.bEdgeRadiusAllowed=sal_True; FASTBOOL bCanConv=ImpCanConvTextToCurve(); rInfo.bCanConvToPath =bCanConv; rInfo.bCanConvToPoly =bCanConv; rInfo.bCanConvToPathLineToArea=bCanConv; rInfo.bCanConvToPolyLineToArea=bCanConv; rInfo.bCanConvToContour = (rInfo.bCanConvToPoly || LineGeometryUsageIsNecessary()); } sal_uInt16 SdrTextObj::GetObjIdentifier() const { return sal_uInt16(eTextKind); } bool SdrTextObj::HasTextImpl( SdrOutliner* pOutliner ) { bool bRet=false; if(pOutliner) { Paragraph* p1stPara=pOutliner->GetParagraph( 0 ); sal_uIntPtr 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 sal_True; } FASTBOOL SdrTextObj::NbcSetAutoGrowHeight(bool bAuto) { if(bTextFrame) { SetObjectItem(SdrTextAutoGrowHeightItem(bAuto)); return sal_True; } return sal_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 = sal_False; SetObjectItem(SdrTextAutoGrowHeightItem(sal_False)); } return sal_True; } return sal_False; } FASTBOOL SdrTextObj::NbcSetMaxTextFrameHeight(long nHgt) { if(bTextFrame) { SetObjectItem(SdrTextMaxFrameHeightItem(nHgt)); return sal_True; } return sal_False; } FASTBOOL SdrTextObj::NbcSetAutoGrowWidth(bool bAuto) { if(bTextFrame) { SetObjectItem(SdrTextAutoGrowWidthItem(bAuto)); return sal_True; } return sal_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 = sal_False; SetObjectItem(SdrTextAutoGrowWidthItem(sal_False)); } return sal_True; } return sal_False; } FASTBOOL SdrTextObj::NbcSetMaxTextFrameWidth(long nWdt) { if(bTextFrame) { SetObjectItem(SdrTextMaxFrameWidthItem(nWdt)); return sal_True; } return sal_False; } FASTBOOL SdrTextObj::NbcSetFitToSize(sal_Bool bFit) { if(bTextFrame) { SetObjectItem(SdrTextFitToSizeTypeItem(bFit)); return sal_True; } return sal_False; } void SdrTextObj::ImpSetContourPolygon( SdrOutliner& rOutliner, Rectangle& rAnchorRect, sal_Bool bLineWidth ) const { basegfx::B2DPolyPolygon aXorPolyPolygon(TakeXorPoly()); basegfx::B2DPolyPolygon* pContourPolyPolygon = 0L; basegfx::B2DHomMatrix aMatrix(basegfx::tools::createTranslateB2DHomMatrix( -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(sal_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, sal_Bool bLineWidth ) const { Rectangle aAnkRect; // Rect innerhalb dem geankert wird TakeTextAnchorRect(aAnkRect); SdrTextVertAdjust eVAdj=GetTextVerticalAdjust(); SdrTextHorzAdjust eHAdj=GetTextHorizontalAdjust(); SdrTextAniKind eAniKind=GetTextAniKind(); SdrTextAniDirection eAniDirection=GetTextAniDirection(); FASTBOOL bContourFrame=IsContourTextFrame(); FASTBOOL bFrame=IsTextFrame(); sal_uIntPtr nStat0=rOutliner.GetControlWord(); Size aNullSize; if (!bContourFrame) { rOutliner.SetControlWord(nStat0|EE_CNTRL_AUTOPAGESIZE); rOutliner.SetMinAutoPaperSize(aNullSize); rOutliner.SetMaxAutoPaperSize(Size(1000000,1000000)); } if (!GetFitToSize() && !bContourFrame) { long nAnkWdt=aAnkRect.GetWidth(); long nAnkHgt=aAnkRect.GetHeight(); if (bFrame) { long nWdt=nAnkWdt; long nHgt=nAnkHgt; // #101684# sal_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) { sal_Bool bHitTest = sal_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.SetFixedCellHeight(((const SdrTextFixedCellHeightItem&)GetMergedItem(SDRATTR_TEXT_USEFIXEDCELLHEIGHT)).GetValue()); } rOutliner.SetUpdateMode(sal_True); rOutliner.SetText(*pPara); } } else { rOutliner.SetTextObj( NULL ); } if (pEdtOutl && !bNoEditText && pPara) delete pPara; rOutliner.SetUpdateMode(sal_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(); sal_Bool bNoStretching(sal_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(sal_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(sal_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 = sal_True; } #endif } unsigned nLoopCount=0; FASTBOOL bNoMoreLoop=sal_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=sal_True; FASTBOOL bChkY=sal_True; if (bNoStretching) { // #35762# evtl. nur proportional moeglich if (nX>nY) { nX=nY; bChkX=sal_False; } else { nY=nX; bChkY=sal_False; } } while (nLoopCount<5 && !bNoMoreLoop) { if (nX<0) nX=-nX; if (nX<1) { nX=1; bNoMoreLoop=sal_True; } if (nX>65535) { nX=65535; bNoMoreLoop=sal_True; } if (nY<0) nY=-nY; if (nY<1) { nY=1; bNoMoreLoop=sal_True; } if (nY>65535) { nY=65535; bNoMoreLoop=sal_True; } // exception, there is no text yet (horizontal case) if(nIsWdt <= 1) { nX = nY; bNoMoreLoop = sal_True; } // #87877# exception, there is no text yet (vertical case) if(nIsHgt <= 1) { nY = nX; bNoMoreLoop = sal_True; } rOutliner.SetGlobalCharStretching((sal_uInt16)nX,(sal_uInt16)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=sal_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; } } 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::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 = new OutlinerParaObject(*pTextObj->getActiveText()->GetOutlinerParaObject()); } } mpText->SetOutlinerParaObject( pNewOutlinerParaObject ); ImpSetTextStyleSheetListeners(); } } basegfx::B2DPolyPolygon SdrTextObj::TakeXorPoly() 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,sal_False,&aAnchor2); rOutliner.Clear(); if (GetFitToSize()) 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=sal_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(sal_False); sal_uInt16 nOutlinerMode = OUTLINERMODE_OUTLINEOBJECT; if ( !IsOutlText() ) nOutlinerMode = OUTLINERMODE_TEXTOBJECT; rOutl.Init( nOutlinerMode ); rOutl.SetGlobalCharStretching(100,100); sal_uIntPtr 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 if(GetFitToSize()) { sal_uIntPtr 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, sal_False, &rAnchorRect); rPaintRect = rTextRect; if (!bContourFrame) { // FitToSize erstmal nicht mit ContourFrame if(GetFitToSize()) { 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(); if( GetModel() ) { MapMode aMapMode(GetModel()->GetScaleUnit(), Point(0,0), GetModel()->GetScaleFraction(), GetModel()->GetScaleFraction()); rOutl.SetRefMapMode(aMapMode); } ImpSetupDrawOutlinerForPaint( bContourFrame, rOutl, aTextRect, aAnchorRect, rPaintRect, aFitXKorreg ); } //////////////////////////////////////////////////////////////////////////////////////////////////// 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 SetRectsDirty(sal_True); } // always invalidate BoundRect on change SetBoundRectDirty(); ActionChanged(); ImpSetTextStyleSheetListeners(); ImpCheckMasterCachable(); } void SdrTextObj::NbcReformatText() { SdrText* pText = getActiveText(); if( pText && pText->GetOutlinerParaObject() ) { pText->ReformatText(); if (bTextFrame) { NbcAdjustTextFrameWidthAndHeight(); } else { // Das SnapRect behaelt seine Groesse bei SetBoundRectDirty(); SetRectsDirty(sal_True); } SetTextSizeDirty(); ActionChanged(); // FME, AW: i22396 // Necessary here since we have no compare operator at the outliner // para object which may detect changes regarding the combination // of outliner para data and configuration (e.g., change of // formatting of text numerals) GetViewContact().flushViewObjectContacts(false); } } 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(); } sal_Bool SdrTextObj::GetFitToSize() const { sal_Bool bType(sal_False); if(!IsAutoGrowWidth()) { bType = ((SdrTextFitToSizeTypeItem&)(GetObjectItem(SDRATTR_TEXT_FITTOSIZE))).GetValue(); } return bType; } void SdrTextObj::ForceOutlinerParaObject() { SdrText* pText = getActiveText(); if( pText && (pText->GetOutlinerParaObject() == 0) ) { sal_uInt16 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 && 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() != (bool)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 && pModel->IsWriter() ) { if(GetAnchorPos().X() || GetAnchorPos().Y()) { aTranslate -= basegfx::B2DTuple(GetAnchorPos().X(), GetAnchorPos().Y()); } } // force MapUnit to 100th mm SfxMapUnit eMapUnit = GetObjectItemSet().GetPool()->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 = basegfx::tools::createScaleShearXRotateTranslateB2DHomMatrix( aScale, basegfx::fTools::equalZero(fShearX) ? 0.0 : tan(fShearX), basegfx::fTools::equalZero(fRotate) ? 0.0 : -fRotate, aTranslate); 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(0.0); double fShearX(0.0); 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 = GetObjectItemSet().GetPool()->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 && 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, sal_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) ? sal_False // Default ist FALSE : ((XFormTextStyleItem&)(GetObjectItemSet().Get(XATTR_FORMTXTSTYLE))).GetValue()!=XFT_NONE; } FASTBOOL SdrTextObj::IsHideContour() const { return (bTextFrame) ? sal_False // Default ist: Nein, kein HideContour; HideContour nicht bei TextFrames : ((XFormTextHideFormItem&)(GetObjectItemSet().Get(XATTR_FORMTXTHIDEFORM))).GetValue(); } FASTBOOL SdrTextObj::IsContourTextFrame() const { return (bTextFrame) ? sal_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(); rOutliner.Draw(&aBlackHole, aPaintPos); pRetval->Stop(); pRetval->WindStart(); // return PaintRectanglePixel and pRetval; rScrollRectangle = aScrollFrameRect; rPaintRectangle = aPaintRect; return pRetval; } // #111096# // Access to TextAnimationAllowed flag 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; } void SdrTextObj::SetObjectItemNoBroadcast(const SfxPoolItem& rItem) { static_cast< sdr::properties::TextProperties& >(GetProperties()).SetObjectItemNoBroadcast(rItem); } ///////////////////////////////////////////////////////////////////////////////////////////////// // // Konzept des TextObjekts: // ~~~~~~~~~~~~~~~~~~~~~~~~ // Attribute/Varianten: // - sal_Bool Textrahmen / beschriftetes Zeichenobjekt // - sal_Bool FontWork (wenn nicht Textrahmen und nicht ContourTextFrame) // - sal_Bool ContourTextFrame (wenn nicht Textrahmen und nicht Fontwork) // - long Drehwinkel (wenn nicht FontWork) // - long Textrahmenabstaende (wenn nicht FontWork) // - sal_Bool FitToSize (wenn nicht FontWork) // - sal_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=sal_True) // oder ein beschriftetes Zeichenobjekt (bTextFrame=sal_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 // - sal_Bool FitToSize spaeter vielleicht // - sal_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 // - ConvertToPoly // - Edit // - Drucken,Speichern, Paint in Nachbarview waerend Edit // - ModelChanged (z.B. durch NachbarView oder Lineale) waerend Edit // - FillColorChanged waerend Edit // - uvm... // /////////////////////////////////////////////////////////////////////////////////////////////////