Line data Source code
1 : /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 : /*
3 : * This file is part of the LibreOffice project.
4 : *
5 : * This Source Code Form is subject to the terms of the Mozilla Public
6 : * License, v. 2.0. If a copy of the MPL was not distributed with this
7 : * file, You can obtain one at http://mozilla.org/MPL/2.0/.
8 : *
9 : * This file incorporates work covered by the following license notice:
10 : *
11 : * Licensed to the Apache Software Foundation (ASF) under one or more
12 : * contributor license agreements. See the NOTICE file distributed
13 : * with this work for additional information regarding copyright
14 : * ownership. The ASF licenses this file to you under the Apache
15 : * License, Version 2.0 (the "License"); you may not use this file
16 : * except in compliance with the License. You may obtain a copy of
17 : * the License at http://www.apache.org/licenses/LICENSE-2.0 .
18 : */
19 :
20 :
21 : #include <comphelper/string.hxx>
22 : #include <svx/svdotext.hxx>
23 : #include <svx/svdpagv.hxx> // for the request in Paint to see whether
24 : #include <svx/svdview.hxx> // the object is currently being edited
25 : #include <svx/svdpage.hxx> // and for AnimationHandler (ticker text)
26 : #include <svx/svdetc.hxx>
27 : #include <svx/svdoutl.hxx>
28 : #include <svx/svdmodel.hxx> // OutlinerDefaults
29 : #include "svx/svdglob.hxx" // Stringcache
30 : #include "svx/svdstr.hrc" // the object's name
31 : #include <editeng/writingmodeitem.hxx>
32 : #include <svx/sdtfchim.hxx>
33 : #include <svtools/colorcfg.hxx>
34 : #include <editeng/editdata.hxx>
35 : #include <editeng/eeitem.hxx>
36 : #include <editeng/editstat.hxx>
37 : #include <editeng/outlobj.hxx>
38 : #include <editeng/editobj.hxx>
39 : #include <editeng/outliner.hxx>
40 : #include <editeng/fhgtitem.hxx>
41 : #include <svl/itempool.hxx>
42 : #include <editeng/adjustitem.hxx>
43 : #include <editeng/flditem.hxx>
44 : #include <svx/xftouit.hxx>
45 : #include <tools/helpers.hxx>
46 : #include <svx/xflgrit.hxx>
47 : #include <svx/svdpool.hxx>
48 : #include <svx/xflclit.hxx>
49 : #include <svl/style.hxx>
50 : #include <editeng/editeng.hxx>
51 : #include <svl/itemiter.hxx>
52 : #include <svx/sdr/properties/textproperties.hxx>
53 : #include <vcl/metaact.hxx>
54 : #include <svx/sdr/contact/viewcontactoftextobj.hxx>
55 : #include <basegfx/tuple/b2dtuple.hxx>
56 : #include <basegfx/matrix/b2dhommatrix.hxx>
57 : #include <basegfx/polygon/b2dpolygon.hxx>
58 : #include <drawinglayer/geometry/viewinformation2d.hxx>
59 : #include <vcl/virdev.hxx>
60 : #include <basegfx/matrix/b2dhommatrixtools.hxx>
61 : #include "svdconv.hxx"
62 :
63 : //////////////////////////////////////////////////////////////////////////////
64 :
65 : using namespace com::sun::star;
66 :
67 : //////////////////////////////////////////////////////////////////////////////
68 : // BaseProperties section
69 :
70 10286 : sdr::properties::BaseProperties* SdrTextObj::CreateObjectSpecificProperties()
71 : {
72 10286 : return new sdr::properties::TextProperties(*this);
73 : }
74 :
75 : //////////////////////////////////////////////////////////////////////////////
76 : // DrawContact section
77 :
78 0 : sdr::contact::ViewContact* SdrTextObj::CreateObjectSpecificViewContact()
79 : {
80 0 : return new sdr::contact::ViewContactOfTextObj(*this);
81 : }
82 :
83 : //////////////////////////////////////////////////////////////////////////////
84 :
85 1855536 : TYPEINIT1(SdrTextObj,SdrAttrObj);
86 :
87 18034 : SdrTextObj::SdrTextObj()
88 : : SdrAttrObj(),
89 : mpText(NULL),
90 : pEdtOutl(NULL),
91 : pFormTextBoundRect(NULL),
92 18034 : eTextKind(OBJ_TEXT)
93 : {
94 18034 : bTextSizeDirty=sal_False;
95 18034 : bTextFrame=sal_False;
96 18034 : bNoShear=sal_False;
97 18034 : bNoRotate=sal_False;
98 18034 : bNoMirror=sal_False;
99 18034 : bDisableAutoWidthOnDragging=sal_False;
100 :
101 18034 : mbInEditMode = sal_False;
102 18034 : mbTextHidden = sal_False;
103 18034 : mbTextAnimationAllowed = sal_True;
104 18034 : maTextEditOffset = Point(0, 0);
105 :
106 : // #i25616#
107 18034 : mbSupportTextIndentingOnLineWidthChange = sal_True;
108 18034 : mbInDownScale = sal_False;
109 18034 : }
110 :
111 76 : SdrTextObj::SdrTextObj(const Rectangle& rNewRect)
112 : : SdrAttrObj(),
113 : aRect(rNewRect),
114 : mpText(NULL),
115 : pEdtOutl(NULL),
116 : pFormTextBoundRect(NULL),
117 76 : eTextKind(OBJ_TEXT)
118 : {
119 76 : bTextSizeDirty=sal_False;
120 76 : bTextFrame=sal_False;
121 76 : bNoShear=sal_False;
122 76 : bNoRotate=sal_False;
123 76 : bNoMirror=sal_False;
124 76 : bDisableAutoWidthOnDragging=sal_False;
125 76 : ImpJustifyRect(aRect);
126 :
127 76 : mbInEditMode = sal_False;
128 76 : mbTextHidden = sal_False;
129 76 : mbTextAnimationAllowed = sal_True;
130 76 : mbInDownScale = sal_False;
131 76 : maTextEditOffset = Point(0, 0);
132 :
133 : // #i25616#
134 76 : mbSupportTextIndentingOnLineWidthChange = sal_True;
135 76 : }
136 :
137 12746 : SdrTextObj::SdrTextObj(SdrObjKind eNewTextKind)
138 : : SdrAttrObj(),
139 : mpText(NULL),
140 : pEdtOutl(NULL),
141 : pFormTextBoundRect(NULL),
142 12746 : eTextKind(eNewTextKind)
143 : {
144 12746 : bTextSizeDirty=sal_False;
145 12746 : bTextFrame=sal_True;
146 12746 : bNoShear=sal_True;
147 12746 : bNoRotate=sal_False;
148 12746 : bNoMirror=sal_True;
149 12746 : bDisableAutoWidthOnDragging=sal_False;
150 :
151 12746 : mbInEditMode = sal_False;
152 12746 : mbTextHidden = sal_False;
153 12746 : mbTextAnimationAllowed = sal_True;
154 12746 : mbInDownScale = sal_False;
155 12746 : maTextEditOffset = Point(0, 0);
156 :
157 : // #i25616#
158 12746 : mbSupportTextIndentingOnLineWidthChange = sal_True;
159 12746 : }
160 :
161 66 : SdrTextObj::SdrTextObj(SdrObjKind eNewTextKind, const Rectangle& rNewRect)
162 : : SdrAttrObj(),
163 : aRect(rNewRect),
164 : mpText(NULL),
165 : pEdtOutl(NULL),
166 : pFormTextBoundRect(NULL),
167 66 : eTextKind(eNewTextKind)
168 : {
169 66 : bTextSizeDirty=sal_False;
170 66 : bTextFrame=sal_True;
171 66 : bNoShear=sal_True;
172 66 : bNoRotate=sal_False;
173 66 : bNoMirror=sal_True;
174 66 : bDisableAutoWidthOnDragging=sal_False;
175 66 : ImpJustifyRect(aRect);
176 :
177 66 : mbInEditMode = sal_False;
178 66 : mbTextHidden = sal_False;
179 66 : mbTextAnimationAllowed = sal_True;
180 66 : mbInDownScale = sal_False;
181 66 : maTextEditOffset = Point(0, 0);
182 :
183 : // #i25616#
184 66 : mbSupportTextIndentingOnLineWidthChange = sal_True;
185 66 : }
186 :
187 61680 : SdrTextObj::~SdrTextObj()
188 : {
189 30840 : if( pModel )
190 : {
191 30703 : SdrOutliner& rOutl = pModel->GetHitTestOutliner();
192 30703 : if( rOutl.GetTextObj() == this )
193 0 : rOutl.SetTextObj( NULL );
194 : }
195 :
196 30840 : delete mpText;
197 :
198 30840 : delete pFormTextBoundRect;
199 :
200 30840 : ImpLinkAbmeldung();
201 30840 : }
202 :
203 0 : void SdrTextObj::FitFrameToTextSize()
204 : {
205 : DBG_ASSERT(pModel!=NULL,"SdrTextObj::FitFrameToTextSize(): pModel=NULL!");
206 0 : ImpJustifyRect(aRect);
207 :
208 0 : SdrText* pText = getActiveText();
209 0 : if( pText!=NULL && pText->GetOutlinerParaObject() && pModel!=NULL)
210 : {
211 0 : SdrOutliner& rOutliner=ImpGetDrawOutliner();
212 0 : rOutliner.SetPaperSize(Size(aRect.Right()-aRect.Left(),aRect.Bottom()-aRect.Top()));
213 0 : rOutliner.SetUpdateMode(sal_True);
214 0 : rOutliner.SetText(*pText->GetOutlinerParaObject());
215 0 : Size aNewSize(rOutliner.CalcTextSize());
216 0 : rOutliner.Clear();
217 0 : aNewSize.Width()++; // because of possible rounding errors
218 0 : aNewSize.Width()+=GetTextLeftDistance()+GetTextRightDistance();
219 0 : aNewSize.Height()+=GetTextUpperDistance()+GetTextLowerDistance();
220 0 : Rectangle aNewRect(aRect);
221 0 : aNewRect.SetSize(aNewSize);
222 0 : ImpJustifyRect(aNewRect);
223 0 : if (aNewRect!=aRect) {
224 0 : SetLogicRect(aNewRect);
225 : }
226 : }
227 0 : }
228 :
229 44 : void SdrTextObj::NbcSetText(const XubString& rStr)
230 : {
231 44 : SdrOutliner& rOutliner=ImpGetDrawOutliner();
232 44 : rOutliner.SetStyleSheet( 0, GetStyleSheet());
233 44 : rOutliner.SetUpdateMode(sal_True);
234 44 : rOutliner.SetText(rStr,rOutliner.GetParagraph( 0 ));
235 44 : OutlinerParaObject* pNewText=rOutliner.CreateParaObject();
236 44 : Size aSiz(rOutliner.CalcTextSize());
237 44 : rOutliner.Clear();
238 44 : NbcSetOutlinerParaObject(pNewText);
239 44 : aTextSize=aSiz;
240 44 : bTextSizeDirty=sal_False;
241 44 : }
242 :
243 7 : void SdrTextObj::SetText(const XubString& rStr)
244 : {
245 7 : Rectangle aBoundRect0; if (pUserCall!=NULL) aBoundRect0=GetLastBoundRect();
246 7 : NbcSetText(rStr);
247 7 : SetChanged();
248 7 : BroadcastObjectChange();
249 7 : SendUserCall(SDRUSERCALL_RESIZE,aBoundRect0);
250 7 : }
251 :
252 0 : void SdrTextObj::NbcSetText(SvStream& rInput, const String& rBaseURL, sal_uInt16 eFormat)
253 : {
254 0 : SdrOutliner& rOutliner=ImpGetDrawOutliner();
255 0 : rOutliner.SetStyleSheet( 0, GetStyleSheet());
256 0 : rOutliner.Read(rInput,rBaseURL,eFormat);
257 0 : OutlinerParaObject* pNewText=rOutliner.CreateParaObject();
258 0 : rOutliner.SetUpdateMode(sal_True);
259 0 : Size aSiz(rOutliner.CalcTextSize());
260 0 : rOutliner.Clear();
261 0 : NbcSetOutlinerParaObject(pNewText);
262 0 : aTextSize=aSiz;
263 0 : bTextSizeDirty=sal_False;
264 0 : }
265 :
266 0 : void SdrTextObj::SetText(SvStream& rInput, const String& rBaseURL, sal_uInt16 eFormat)
267 : {
268 0 : Rectangle aBoundRect0; if (pUserCall!=NULL) aBoundRect0=GetLastBoundRect();
269 0 : NbcSetText(rInput,rBaseURL,eFormat);
270 0 : SetChanged();
271 0 : BroadcastObjectChange();
272 0 : SendUserCall(SDRUSERCALL_RESIZE,aBoundRect0);
273 0 : }
274 :
275 6 : const Size& SdrTextObj::GetTextSize() const
276 : {
277 6 : if (bTextSizeDirty)
278 : {
279 1 : Size aSiz;
280 1 : SdrText* pText = getActiveText();
281 1 : if( pText && pText->GetOutlinerParaObject ())
282 : {
283 1 : SdrOutliner& rOutliner=ImpGetDrawOutliner();
284 1 : rOutliner.SetText(*pText->GetOutlinerParaObject());
285 1 : rOutliner.SetUpdateMode(sal_True);
286 1 : aSiz=rOutliner.CalcTextSize();
287 1 : rOutliner.Clear();
288 : }
289 : // casting to nonconst twice
290 1 : ((SdrTextObj*)this)->aTextSize=aSiz;
291 1 : ((SdrTextObj*)this)->bTextSizeDirty=sal_False;
292 : }
293 6 : return aTextSize;
294 : }
295 :
296 143370 : bool SdrTextObj::IsAutoGrowHeight() const
297 : {
298 143370 : if(!bTextFrame)
299 0 : return sal_False; // AutoGrow only together with TextFrames
300 :
301 143370 : const SfxItemSet& rSet = GetObjectItemSet();
302 143370 : sal_Bool bRet = ((SdrTextAutoGrowHeightItem&)(rSet.Get(SDRATTR_TEXT_AUTOGROWHEIGHT))).GetValue();
303 :
304 143370 : if(bRet)
305 : {
306 136068 : SdrTextAniKind eAniKind = ((SdrTextAniKindItem&)(rSet.Get(SDRATTR_TEXT_ANIKIND))).GetValue();
307 :
308 136068 : if(eAniKind == SDRTEXTANI_SCROLL || eAniKind == SDRTEXTANI_ALTERNATE || eAniKind == SDRTEXTANI_SLIDE)
309 : {
310 0 : SdrTextAniDirection eDirection = ((SdrTextAniDirectionItem&)(rSet.Get(SDRATTR_TEXT_ANIDIRECTION))).GetValue();
311 :
312 0 : if(eDirection == SDRTEXTANI_UP || eDirection == SDRTEXTANI_DOWN)
313 : {
314 0 : bRet = sal_False;
315 : }
316 : }
317 : }
318 143370 : return bRet;
319 : }
320 :
321 204770 : bool SdrTextObj::IsAutoGrowWidth() const
322 : {
323 204770 : if(!bTextFrame)
324 46 : return sal_False; // AutoGrow only together with TextFrames
325 :
326 204724 : const SfxItemSet& rSet = GetObjectItemSet();
327 204724 : sal_Bool bRet = ((SdrTextAutoGrowHeightItem&)(rSet.Get(SDRATTR_TEXT_AUTOGROWWIDTH))).GetValue();
328 :
329 204724 : sal_Bool bInEditMOde = IsInEditMode();
330 :
331 204724 : if(!bInEditMOde && bRet)
332 : {
333 99226 : SdrTextAniKind eAniKind = ((SdrTextAniKindItem&)(rSet.Get(SDRATTR_TEXT_ANIKIND))).GetValue();
334 :
335 99226 : if(eAniKind == SDRTEXTANI_SCROLL || eAniKind == SDRTEXTANI_ALTERNATE || eAniKind == SDRTEXTANI_SLIDE)
336 : {
337 0 : SdrTextAniDirection eDirection = ((SdrTextAniDirectionItem&)(rSet.Get(SDRATTR_TEXT_ANIDIRECTION))).GetValue();
338 :
339 0 : if(eDirection == SDRTEXTANI_LEFT || eDirection == SDRTEXTANI_RIGHT)
340 : {
341 0 : bRet = sal_False;
342 : }
343 : }
344 : }
345 204724 : return bRet;
346 : }
347 :
348 28988 : SdrTextHorzAdjust SdrTextObj::GetTextHorizontalAdjust() const
349 : {
350 28988 : return GetTextHorizontalAdjust(GetObjectItemSet());
351 : }
352 :
353 42693 : SdrTextHorzAdjust SdrTextObj::GetTextHorizontalAdjust(const SfxItemSet& rSet) const
354 : {
355 42693 : if(IsContourTextFrame())
356 0 : return SDRTEXTHORZADJUST_BLOCK;
357 :
358 42693 : SdrTextHorzAdjust eRet = ((SdrTextHorzAdjustItem&)(rSet.Get(SDRATTR_TEXT_HORZADJUST))).GetValue();
359 :
360 42693 : sal_Bool bInEditMode = IsInEditMode();
361 :
362 42693 : if(!bInEditMode && eRet == SDRTEXTHORZADJUST_BLOCK)
363 : {
364 1789 : SdrTextAniKind eAniKind = ((SdrTextAniKindItem&)(rSet.Get(SDRATTR_TEXT_ANIKIND))).GetValue();
365 :
366 1789 : if(eAniKind == SDRTEXTANI_SCROLL || eAniKind == SDRTEXTANI_ALTERNATE || eAniKind == SDRTEXTANI_SLIDE)
367 : {
368 0 : SdrTextAniDirection eDirection = ((SdrTextAniDirectionItem&)(rSet.Get(SDRATTR_TEXT_ANIDIRECTION))).GetValue();
369 :
370 0 : if(eDirection == SDRTEXTANI_LEFT || eDirection == SDRTEXTANI_RIGHT)
371 : {
372 0 : eRet = SDRTEXTHORZADJUST_LEFT;
373 : }
374 : }
375 : }
376 :
377 42693 : return eRet;
378 : } // defaults: BLOCK (justify) for text frame, CENTER for captions of drawing objects
379 :
380 62035 : SdrTextVertAdjust SdrTextObj::GetTextVerticalAdjust() const
381 : {
382 62035 : return GetTextVerticalAdjust(GetObjectItemSet());
383 : }
384 :
385 75740 : SdrTextVertAdjust SdrTextObj::GetTextVerticalAdjust(const SfxItemSet& rSet) const
386 : {
387 75740 : if(IsContourTextFrame())
388 0 : return SDRTEXTVERTADJUST_TOP;
389 :
390 : // Take care for vertical text animation here
391 75740 : SdrTextVertAdjust eRet = ((SdrTextVertAdjustItem&)(rSet.Get(SDRATTR_TEXT_VERTADJUST))).GetValue();
392 75740 : sal_Bool bInEditMode = IsInEditMode();
393 :
394 : // Take care for vertical text animation here
395 75740 : if(!bInEditMode && eRet == SDRTEXTVERTADJUST_BLOCK)
396 : {
397 0 : SdrTextAniKind eAniKind = ((SdrTextAniKindItem&)(rSet.Get(SDRATTR_TEXT_ANIKIND))).GetValue();
398 :
399 0 : if(eAniKind == SDRTEXTANI_SCROLL || eAniKind == SDRTEXTANI_ALTERNATE || eAniKind == SDRTEXTANI_SLIDE)
400 : {
401 0 : SdrTextAniDirection eDirection = ((SdrTextAniDirectionItem&)(rSet.Get(SDRATTR_TEXT_ANIDIRECTION))).GetValue();
402 :
403 0 : if(eDirection == SDRTEXTANI_LEFT || eDirection == SDRTEXTANI_RIGHT)
404 : {
405 0 : eRet = SDRTEXTVERTADJUST_TOP;
406 : }
407 : }
408 : }
409 :
410 75740 : return eRet;
411 : } // defaults: TOP for text frame, CENTER for captions of drawing objects
412 :
413 84098 : void SdrTextObj::ImpJustifyRect(Rectangle& rRect) const
414 : {
415 84098 : if (!rRect.IsEmpty()) {
416 82738 : rRect.Justify();
417 82738 : if (rRect.Left()==rRect.Right()) rRect.Right()++;
418 82738 : if (rRect.Top()==rRect.Bottom()) rRect.Bottom()++;
419 : }
420 84098 : }
421 :
422 55276 : void SdrTextObj::ImpCheckShear()
423 : {
424 55276 : if (bNoShear && aGeo.nShearWink!=0) {
425 0 : aGeo.nShearWink=0;
426 0 : aGeo.nTan=0;
427 : }
428 55276 : }
429 :
430 0 : void SdrTextObj::TakeObjInfo(SdrObjTransformInfoRec& rInfo) const
431 : {
432 0 : bool bNoTextFrame=!IsTextFrame();
433 0 : rInfo.bResizeFreeAllowed=bNoTextFrame || aGeo.nDrehWink%9000==0;
434 0 : rInfo.bResizePropAllowed=sal_True;
435 0 : rInfo.bRotateFreeAllowed=sal_True;
436 0 : rInfo.bRotate90Allowed =sal_True;
437 0 : rInfo.bMirrorFreeAllowed=bNoTextFrame;
438 0 : rInfo.bMirror45Allowed =bNoTextFrame;
439 0 : rInfo.bMirror90Allowed =bNoTextFrame;
440 :
441 : // allow transparency
442 0 : rInfo.bTransparenceAllowed = sal_True;
443 :
444 : // gradient depends on fillstyle
445 0 : XFillStyle eFillStyle = ((XFillStyleItem&)(GetObjectItem(XATTR_FILLSTYLE))).GetValue();
446 0 : rInfo.bGradientAllowed = (eFillStyle == XFILL_GRADIENT);
447 0 : rInfo.bShearAllowed =bNoTextFrame;
448 0 : rInfo.bEdgeRadiusAllowed=sal_True;
449 0 : bool bCanConv=ImpCanConvTextToCurve();
450 0 : rInfo.bCanConvToPath =bCanConv;
451 0 : rInfo.bCanConvToPoly =bCanConv;
452 0 : rInfo.bCanConvToPathLineToArea=bCanConv;
453 0 : rInfo.bCanConvToPolyLineToArea=bCanConv;
454 0 : rInfo.bCanConvToContour = (rInfo.bCanConvToPoly || LineGeometryUsageIsNecessary());
455 0 : }
456 :
457 0 : sal_uInt16 SdrTextObj::GetObjIdentifier() const
458 : {
459 0 : return sal_uInt16(eTextKind);
460 : }
461 :
462 13586 : bool SdrTextObj::HasTextImpl( SdrOutliner* pOutliner )
463 : {
464 13586 : bool bRet=false;
465 13586 : if(pOutliner)
466 : {
467 0 : Paragraph* p1stPara=pOutliner->GetParagraph( 0 );
468 0 : sal_Int32 nParaAnz=pOutliner->GetParagraphCount();
469 0 : if(p1stPara==NULL)
470 0 : nParaAnz=0;
471 :
472 0 : if(nParaAnz==1)
473 : {
474 : // if it is only one paragraph, check if that paragraph is empty
475 0 : XubString aStr(pOutliner->GetText(p1stPara));
476 :
477 0 : if(!aStr.Len())
478 0 : nParaAnz = 0;
479 : }
480 :
481 0 : bRet= nParaAnz!=0;
482 : }
483 13586 : return bRet;
484 : }
485 :
486 0 : bool SdrTextObj::HasEditText() const
487 : {
488 0 : return HasTextImpl( pEdtOutl );
489 : }
490 :
491 83060 : void SdrTextObj::SetPage(SdrPage* pNewPage)
492 : {
493 83060 : bool bRemove=pNewPage==NULL && pPage!=NULL;
494 83060 : bool bInsert=pNewPage!=NULL && pPage==NULL;
495 83060 : bool bLinked=IsLinkedText();
496 :
497 83060 : if (bLinked && bRemove) {
498 0 : ImpLinkAbmeldung();
499 : }
500 :
501 83060 : SdrAttrObj::SetPage(pNewPage);
502 :
503 83060 : if (bLinked && bInsert) {
504 0 : ImpLinkAnmeldung();
505 : }
506 83060 : }
507 :
508 58822 : void SdrTextObj::SetModel(SdrModel* pNewModel)
509 : {
510 58822 : SdrModel* pOldModel=pModel;
511 58822 : bool bLinked=IsLinkedText();
512 58822 : bool bChg=pNewModel!=pModel;
513 :
514 58822 : if (bLinked && bChg)
515 : {
516 0 : ImpLinkAbmeldung();
517 : }
518 :
519 58822 : SdrAttrObj::SetModel(pNewModel);
520 :
521 58822 : if( bChg )
522 : {
523 30737 : if( pNewModel != 0 && pOldModel != 0 )
524 0 : SetTextSizeDirty();
525 :
526 30737 : sal_Int32 nCount = getTextCount();
527 61474 : for( sal_Int32 nText = 0; nText < nCount; nText++ )
528 : {
529 30737 : SdrText* pText = getText( nText );
530 30737 : if( pText )
531 30737 : pText->SetModel( pNewModel );
532 : }
533 : }
534 :
535 58822 : if (bLinked && bChg)
536 : {
537 0 : ImpLinkAnmeldung();
538 : }
539 58822 : }
540 :
541 0 : bool SdrTextObj::NbcSetEckenradius(long nRad)
542 : {
543 0 : SetObjectItem(SdrEckenradiusItem(nRad));
544 0 : return true;
545 : }
546 :
547 40553 : bool SdrTextObj::NbcSetMinTextFrameHeight(long nHgt)
548 : {
549 40553 : if( bTextFrame && ( !pModel || !pModel->isLocked() ) ) // #i44922#
550 : {
551 884 : SetObjectItem(SdrTextMinFrameHeightItem(nHgt));
552 :
553 : // use bDisableAutoWidthOnDragging as
554 : // bDisableAutoHeightOnDragging if vertical.
555 884 : if(IsVerticalWriting() && bDisableAutoWidthOnDragging)
556 : {
557 0 : bDisableAutoWidthOnDragging = sal_False;
558 0 : SetObjectItem(SdrTextAutoGrowHeightItem(sal_False));
559 : }
560 :
561 884 : return true;
562 : }
563 39669 : return false;
564 : }
565 :
566 15748 : bool SdrTextObj::NbcSetMinTextFrameWidth(long nWdt)
567 : {
568 15748 : if( bTextFrame && ( !pModel || !pModel->isLocked() ) ) // #i44922#
569 : {
570 0 : SetObjectItem(SdrTextMinFrameWidthItem(nWdt));
571 :
572 : // use bDisableAutoWidthOnDragging only
573 : // when not vertical.
574 0 : if(!IsVerticalWriting() && bDisableAutoWidthOnDragging)
575 : {
576 0 : bDisableAutoWidthOnDragging = sal_False;
577 0 : SetObjectItem(SdrTextAutoGrowWidthItem(sal_False));
578 : }
579 :
580 0 : return true;
581 : }
582 15748 : return false;
583 : }
584 :
585 0 : void SdrTextObj::ImpSetContourPolygon( SdrOutliner& rOutliner, Rectangle& rAnchorRect, sal_Bool bLineWidth ) const
586 : {
587 0 : basegfx::B2DPolyPolygon aXorPolyPolygon(TakeXorPoly());
588 0 : basegfx::B2DPolyPolygon* pContourPolyPolygon = 0L;
589 : basegfx::B2DHomMatrix aMatrix(basegfx::tools::createTranslateB2DHomMatrix(
590 0 : -rAnchorRect.Left(), -rAnchorRect.Top()));
591 :
592 0 : if(aGeo.nDrehWink)
593 : {
594 : // Unrotate!
595 0 : aMatrix.rotate(-aGeo.nDrehWink * nPi180);
596 : }
597 :
598 0 : aXorPolyPolygon.transform(aMatrix);
599 :
600 0 : if( bLineWidth )
601 : {
602 : // Take line width into account.
603 : // When doing the hit test, avoid this. (Performance!)
604 :
605 : // test if shadow needs to be avoided for TakeContour()
606 0 : const SfxItemSet& rSet = GetObjectItemSet();
607 0 : sal_Bool bShadowOn = ((SdrShadowItem&)(rSet.Get(SDRATTR_SHADOW))).GetValue();
608 :
609 : // #i33696#
610 : // Remember TextObject currently set at the DrawOutliner, it WILL be
611 : // replaced during calculating the outline since it uses an own paint
612 : // and that one uses the DrawOutliner, too.
613 0 : const SdrTextObj* pLastTextObject = rOutliner.GetTextObj();
614 :
615 0 : if(bShadowOn)
616 : {
617 : // force shadow off
618 0 : SdrObject* pCopy = Clone();
619 0 : pCopy->SetMergedItem(SdrShadowItem(sal_False));
620 0 : *pContourPolyPolygon = pCopy->TakeContour();
621 0 : SdrObject::Free( pCopy );
622 : }
623 : else
624 : {
625 0 : *pContourPolyPolygon = TakeContour();
626 : }
627 :
628 : // #i33696#
629 : // restore remembered text object
630 0 : if(pLastTextObject != rOutliner.GetTextObj())
631 : {
632 0 : rOutliner.SetTextObj(pLastTextObject);
633 : }
634 :
635 0 : pContourPolyPolygon->transform(aMatrix);
636 : }
637 :
638 0 : rOutliner.SetPolygon(aXorPolyPolygon, pContourPolyPolygon);
639 0 : }
640 :
641 0 : void SdrTextObj::TakeUnrotatedSnapRect(Rectangle& rRect) const
642 : {
643 0 : rRect=aRect;
644 0 : }
645 :
646 0 : void SdrTextObj::TakeTextAnchorRect(Rectangle& rAnchorRect) const
647 : {
648 0 : long nLeftDist=GetTextLeftDistance();
649 0 : long nRightDist=GetTextRightDistance();
650 0 : long nUpperDist=GetTextUpperDistance();
651 0 : long nLowerDist=GetTextLowerDistance();
652 0 : Rectangle aAnkRect(aRect); // the rectangle in which we anchor
653 0 : bool bFrame=IsTextFrame();
654 0 : if (!bFrame) {
655 0 : TakeUnrotatedSnapRect(aAnkRect);
656 : }
657 0 : Point aRotateRef(aAnkRect.TopLeft());
658 0 : aAnkRect.Left()+=nLeftDist;
659 0 : aAnkRect.Top()+=nUpperDist;
660 0 : aAnkRect.Right()-=nRightDist;
661 0 : aAnkRect.Bottom()-=nLowerDist;
662 :
663 : // Since sizes may be bigger than the object bounds it is necessary to
664 : // justify the rect now.
665 0 : ImpJustifyRect(aAnkRect);
666 :
667 0 : if (bFrame) {
668 : // TODO: Optimize this.
669 0 : if (aAnkRect.GetWidth()<2) aAnkRect.Right()=aAnkRect.Left()+1; // minimum size h and v: 2 px
670 0 : if (aAnkRect.GetHeight()<2) aAnkRect.Bottom()=aAnkRect.Top()+1;
671 : }
672 0 : if (aGeo.nDrehWink!=0) {
673 0 : Point aTmpPt(aAnkRect.TopLeft());
674 0 : RotatePoint(aTmpPt,aRotateRef,aGeo.nSin,aGeo.nCos);
675 0 : aTmpPt-=aAnkRect.TopLeft();
676 0 : aAnkRect.Move(aTmpPt.X(),aTmpPt.Y());
677 : }
678 0 : rAnchorRect=aAnkRect;
679 0 : }
680 :
681 0 : void SdrTextObj::TakeTextRect( SdrOutliner& rOutliner, Rectangle& rTextRect, bool bNoEditText,
682 : Rectangle* pAnchorRect, bool bLineWidth ) const
683 : {
684 0 : Rectangle aAnkRect; // the rectangle in which we anchor
685 0 : TakeTextAnchorRect(aAnkRect);
686 0 : SdrTextVertAdjust eVAdj=GetTextVerticalAdjust();
687 0 : SdrTextHorzAdjust eHAdj=GetTextHorizontalAdjust();
688 0 : SdrTextAniKind eAniKind=GetTextAniKind();
689 0 : SdrTextAniDirection eAniDirection=GetTextAniDirection();
690 :
691 0 : bool bFitToSize(IsFitToSize());
692 0 : bool bContourFrame=IsContourTextFrame();
693 :
694 0 : bool bFrame=IsTextFrame();
695 0 : sal_uIntPtr nStat0=rOutliner.GetControlWord();
696 0 : Size aNullSize;
697 0 : if (!bContourFrame)
698 : {
699 0 : rOutliner.SetControlWord(nStat0|EE_CNTRL_AUTOPAGESIZE);
700 0 : rOutliner.SetMinAutoPaperSize(aNullSize);
701 0 : rOutliner.SetMaxAutoPaperSize(Size(1000000,1000000));
702 : }
703 :
704 0 : if (!bFitToSize && !bContourFrame)
705 : {
706 0 : long nAnkWdt=aAnkRect.GetWidth();
707 0 : long nAnkHgt=aAnkRect.GetHeight();
708 0 : if (bFrame)
709 : {
710 0 : long nWdt=nAnkWdt;
711 0 : long nHgt=nAnkHgt;
712 :
713 0 : sal_Bool bInEditMode = IsInEditMode();
714 :
715 0 : if (!bInEditMode && (eAniKind==SDRTEXTANI_SCROLL || eAniKind==SDRTEXTANI_ALTERNATE || eAniKind==SDRTEXTANI_SLIDE))
716 : {
717 : // unlimited paper size for ticker text
718 0 : if (eAniDirection==SDRTEXTANI_LEFT || eAniDirection==SDRTEXTANI_RIGHT) nWdt=1000000;
719 0 : if (eAniDirection==SDRTEXTANI_UP || eAniDirection==SDRTEXTANI_DOWN) nHgt=1000000;
720 : }
721 :
722 : // #i119885# Do not limit/force height to geometrical frame (vice versa for vertical writing)
723 0 : if(IsVerticalWriting())
724 : {
725 0 : nWdt = 1000000;
726 : }
727 : else
728 : {
729 0 : nHgt = 1000000;
730 : }
731 :
732 0 : rOutliner.SetMaxAutoPaperSize(Size(nWdt,nHgt));
733 : }
734 :
735 : // New try with _BLOCK for hor and ver after completely
736 : // supporting full width for vertical text.
737 0 : if(SDRTEXTHORZADJUST_BLOCK == eHAdj && !IsVerticalWriting())
738 : {
739 0 : rOutliner.SetMinAutoPaperSize(Size(nAnkWdt, 0));
740 : }
741 :
742 0 : if(SDRTEXTVERTADJUST_BLOCK == eVAdj && IsVerticalWriting())
743 : {
744 0 : rOutliner.SetMinAutoPaperSize(Size(0, nAnkHgt));
745 : }
746 : }
747 :
748 0 : rOutliner.SetPaperSize(aNullSize);
749 0 : if (bContourFrame)
750 0 : ImpSetContourPolygon( rOutliner, aAnkRect, bLineWidth );
751 :
752 : // put text into the outliner, if available from the edit outliner
753 0 : SdrText* pText = getActiveText();
754 0 : OutlinerParaObject* pOutlinerParaObject = pText ? pText->GetOutlinerParaObject() : 0;
755 0 : OutlinerParaObject* pPara = (pEdtOutl && !bNoEditText) ? pEdtOutl->CreateParaObject() : pOutlinerParaObject;
756 :
757 0 : if (pPara)
758 : {
759 0 : bool bHitTest = false;
760 0 : if( pModel )
761 0 : bHitTest = &pModel->GetHitTestOutliner() == &rOutliner;
762 :
763 0 : const SdrTextObj* pTestObj = rOutliner.GetTextObj();
764 0 : if( !pTestObj || !bHitTest || pTestObj != this ||
765 0 : pTestObj->GetOutlinerParaObject() != pOutlinerParaObject )
766 : {
767 0 : if( bHitTest ) // #i33696# take back fix #i27510#
768 : {
769 0 : rOutliner.SetTextObj( this );
770 0 : rOutliner.SetFixedCellHeight(((const SdrTextFixedCellHeightItem&)GetMergedItem(SDRATTR_TEXT_USEFIXEDCELLHEIGHT)).GetValue());
771 : }
772 :
773 0 : rOutliner.SetUpdateMode(sal_True);
774 0 : rOutliner.SetText(*pPara);
775 : }
776 : }
777 : else
778 : {
779 0 : rOutliner.SetTextObj( NULL );
780 : }
781 :
782 0 : if (pEdtOutl && !bNoEditText && pPara)
783 0 : delete pPara;
784 :
785 0 : rOutliner.SetUpdateMode(sal_True);
786 0 : rOutliner.SetControlWord(nStat0);
787 :
788 0 : if( pText )
789 0 : pText->CheckPortionInfo(rOutliner);
790 :
791 0 : Point aTextPos(aAnkRect.TopLeft());
792 0 : Size aTextSiz(rOutliner.GetPaperSize()); // GetPaperSize() adds a little tolerance, right?
793 :
794 : // For draw objects containing text correct hor/ver alignment if text is bigger
795 : // than the object itself. Without that correction, the text would always be
796 : // formatted to the left edge (or top edge when vertical) of the draw object.
797 0 : if(!IsTextFrame())
798 : {
799 0 : if(aAnkRect.GetWidth() < aTextSiz.Width() && !IsVerticalWriting())
800 : {
801 : // Horizontal case here. Correct only if eHAdj == SDRTEXTHORZADJUST_BLOCK,
802 : // else the alignment is wanted.
803 0 : if(SDRTEXTHORZADJUST_BLOCK == eHAdj)
804 : {
805 0 : eHAdj = SDRTEXTHORZADJUST_CENTER;
806 : }
807 : }
808 :
809 0 : if(aAnkRect.GetHeight() < aTextSiz.Height() && IsVerticalWriting())
810 : {
811 : // Vertical case here. Correct only if eHAdj == SDRTEXTVERTADJUST_BLOCK,
812 : // else the alignment is wanted.
813 0 : if(SDRTEXTVERTADJUST_BLOCK == eVAdj)
814 : {
815 0 : eVAdj = SDRTEXTVERTADJUST_CENTER;
816 : }
817 : }
818 : }
819 :
820 0 : if (eHAdj==SDRTEXTHORZADJUST_CENTER || eHAdj==SDRTEXTHORZADJUST_RIGHT)
821 : {
822 0 : long nFreeWdt=aAnkRect.GetWidth()-aTextSiz.Width();
823 0 : if (eHAdj==SDRTEXTHORZADJUST_CENTER)
824 0 : aTextPos.X()+=nFreeWdt/2;
825 0 : if (eHAdj==SDRTEXTHORZADJUST_RIGHT)
826 0 : aTextPos.X()+=nFreeWdt;
827 : }
828 0 : if (eVAdj==SDRTEXTVERTADJUST_CENTER || eVAdj==SDRTEXTVERTADJUST_BOTTOM)
829 : {
830 0 : long nFreeHgt=aAnkRect.GetHeight()-aTextSiz.Height();
831 0 : if (eVAdj==SDRTEXTVERTADJUST_CENTER)
832 0 : aTextPos.Y()+=nFreeHgt/2;
833 0 : if (eVAdj==SDRTEXTVERTADJUST_BOTTOM)
834 0 : aTextPos.Y()+=nFreeHgt;
835 : }
836 0 : if (aGeo.nDrehWink!=0)
837 0 : RotatePoint(aTextPos,aAnkRect.TopLeft(),aGeo.nSin,aGeo.nCos);
838 :
839 0 : if (pAnchorRect)
840 0 : *pAnchorRect=aAnkRect;
841 :
842 : // rTextRect might not be correct in some cases at ContourFrame
843 0 : rTextRect=Rectangle(aTextPos,aTextSiz);
844 0 : if (bContourFrame)
845 0 : rTextRect=aAnkRect;
846 0 : }
847 :
848 13586 : OutlinerParaObject* SdrTextObj::GetEditOutlinerParaObject() const
849 : {
850 13586 : OutlinerParaObject* pPara=NULL;
851 13586 : if( HasTextImpl( pEdtOutl ) )
852 : {
853 0 : sal_Int32 nParaAnz = pEdtOutl->GetParagraphCount();
854 0 : pPara = pEdtOutl->CreateParaObject(0, nParaAnz);
855 : }
856 13586 : return pPara;
857 : }
858 :
859 0 : void SdrTextObj::ImpSetCharStretching(SdrOutliner& rOutliner, const Size& rTextSize, const Size& rShapeSize, Fraction& rFitXKorreg) const
860 : {
861 0 : OutputDevice* pOut = rOutliner.GetRefDevice();
862 0 : bool bNoStretching(false);
863 :
864 0 : if(pOut && pOut->GetOutDevType() == OUTDEV_PRINTER)
865 : {
866 : // check whether CharStretching is possible at all
867 0 : GDIMetaFile* pMtf = pOut->GetConnectMetaFile();
868 0 : OUString aTestString(static_cast<sal_Unicode>('J'));
869 :
870 0 : if(pMtf && (!pMtf->IsRecord() || pMtf->IsPause()))
871 0 : pMtf = NULL;
872 :
873 0 : if(pMtf)
874 0 : pMtf->Pause(sal_True);
875 :
876 0 : Font aFontMerk(pOut->GetFont());
877 0 : Font aTmpFont( OutputDevice::GetDefaultFont( DEFAULTFONT_SERIF, LANGUAGE_SYSTEM, DEFAULTFONT_FLAGS_ONLYONE ) );
878 :
879 0 : aTmpFont.SetSize(Size(0,100));
880 0 : pOut->SetFont(aTmpFont);
881 0 : Size aSize1(pOut->GetTextWidth(aTestString), pOut->GetTextHeight());
882 0 : aTmpFont.SetSize(Size(800,100));
883 0 : pOut->SetFont(aTmpFont);
884 0 : Size aSize2(pOut->GetTextWidth(aTestString), pOut->GetTextHeight());
885 0 : pOut->SetFont(aFontMerk);
886 :
887 0 : if(pMtf)
888 0 : pMtf->Pause(sal_False);
889 :
890 0 : bNoStretching = (aSize1 == aSize2);
891 :
892 : #ifdef WNT
893 : // Windows zooms the font proportionally when using Size(100,500),
894 : // we don't like that.
895 : if(aSize2.Height() >= aSize1.Height() * 2)
896 : {
897 : bNoStretching = true;
898 : }
899 : #endif
900 : }
901 0 : unsigned nLoopCount=0;
902 0 : bool bNoMoreLoop = false;
903 0 : long nXDiff0=0x7FFFFFFF;
904 0 : long nWantWdt=rShapeSize.Width();
905 0 : long nIsWdt=rTextSize.Width();
906 0 : if (nIsWdt==0) nIsWdt=1;
907 :
908 0 : long nWantHgt=rShapeSize.Height();
909 0 : long nIsHgt=rTextSize.Height();
910 0 : if (nIsHgt==0) nIsHgt=1;
911 :
912 0 : long nXTolPl=nWantWdt/100; // tolerance: +1%
913 0 : long nXTolMi=nWantWdt/25; // tolerance: -4%
914 0 : long nXKorr =nWantWdt/20; // correction scale: 5%
915 :
916 0 : long nX=(nWantWdt*100) /nIsWdt; // calculate X stretching
917 0 : long nY=(nWantHgt*100) /nIsHgt; // calculate Y stretching
918 0 : bool bChkX = true;
919 0 : if (bNoStretching) { // might only be be possible proportionally
920 0 : if (nX>nY) { nX=nY; bChkX=sal_False; }
921 0 : else { nY=nX; }
922 : }
923 :
924 0 : while (nLoopCount<5 && !bNoMoreLoop) {
925 0 : if (nX<0) nX=-nX;
926 0 : if (nX<1) { nX=1; bNoMoreLoop = true; }
927 0 : if (nX>65535) { nX=65535; bNoMoreLoop = true; }
928 :
929 0 : if (nY<0) nY=-nY;
930 0 : if (nY<1) { nY=1; bNoMoreLoop = true; }
931 0 : if (nY>65535) { nY=65535; bNoMoreLoop = true; }
932 :
933 : // exception, there is no text yet (horizontal case)
934 0 : if(nIsWdt <= 1)
935 : {
936 0 : nX = nY;
937 0 : bNoMoreLoop = true;
938 : }
939 :
940 : // exception, there is no text yet (vertical case)
941 0 : if(nIsHgt <= 1)
942 : {
943 0 : nY = nX;
944 0 : bNoMoreLoop = true;
945 : }
946 :
947 0 : rOutliner.SetGlobalCharStretching((sal_uInt16)nX,(sal_uInt16)nY);
948 0 : nLoopCount++;
949 0 : Size aSiz(rOutliner.CalcTextSize());
950 0 : long nXDiff=aSiz.Width()-nWantWdt;
951 0 : rFitXKorreg=Fraction(nWantWdt,aSiz.Width());
952 0 : if (((nXDiff>=nXTolMi || !bChkX) && nXDiff<=nXTolPl) || nXDiff==nXDiff0) {
953 0 : bNoMoreLoop = true;
954 : } else {
955 : // correct stretching factors
956 0 : long nMul=nWantWdt;
957 0 : long nDiv=aSiz.Width();
958 0 : if (std::abs(nXDiff)<=2*nXKorr) {
959 0 : if (nMul>nDiv) nDiv+=(nMul-nDiv)/2; // but only add half of what we calculated,
960 0 : else nMul+=(nDiv-nMul)/2; // because the EditEngine calculates wrongly later on
961 : }
962 0 : nX=nX*nMul/nDiv;
963 0 : if (bNoStretching) nY=nX;
964 : }
965 0 : nXDiff0=nXDiff;
966 : }
967 0 : }
968 :
969 60 : void SdrTextObj::TakeObjNameSingul(XubString& rName) const
970 : {
971 60 : XubString aStr;
972 :
973 60 : switch(eTextKind)
974 : {
975 : case OBJ_OUTLINETEXT:
976 : {
977 8 : aStr = ImpGetResStr(STR_ObjNameSingulOUTLINETEXT);
978 8 : break;
979 : }
980 :
981 : case OBJ_TITLETEXT :
982 : {
983 14 : aStr = ImpGetResStr(STR_ObjNameSingulTITLETEXT);
984 14 : break;
985 : }
986 :
987 : default:
988 : {
989 38 : if(IsLinkedText())
990 0 : aStr = ImpGetResStr(STR_ObjNameSingulTEXTLNK);
991 : else
992 38 : aStr = ImpGetResStr(STR_ObjNameSingulTEXT);
993 38 : break;
994 : }
995 : }
996 :
997 60 : OutlinerParaObject* pOutlinerParaObject = GetOutlinerParaObject();
998 60 : if(pOutlinerParaObject && eTextKind != OBJ_OUTLINETEXT)
999 : {
1000 : // shouldn't currently cause any problems at OUTLINETEXT
1001 52 : XubString aStr2(comphelper::string::stripStart(pOutlinerParaObject->GetTextObject().GetText(0), ' '));
1002 :
1003 : // avoid non expanded text portions in object name
1004 : // (second condition is new)
1005 52 : if(aStr2.Len() && aStr2.Search(sal_Unicode(255)) == STRING_NOTFOUND)
1006 : {
1007 : // space between ResStr and content text
1008 52 : aStr += sal_Unicode(' ');
1009 :
1010 52 : aStr += sal_Unicode('\'');
1011 :
1012 52 : if(aStr2.Len() > 10)
1013 : {
1014 18 : aStr2.Erase(8);
1015 18 : aStr2.AppendAscii("...", 3);
1016 : }
1017 :
1018 52 : aStr += aStr2;
1019 52 : aStr += sal_Unicode('\'');
1020 52 : }
1021 : }
1022 :
1023 60 : rName = aStr;
1024 :
1025 60 : String aName( GetName() );
1026 60 : if(aName.Len())
1027 : {
1028 0 : rName += sal_Unicode(' ');
1029 0 : rName += sal_Unicode('\'');
1030 0 : rName += aName;
1031 0 : rName += sal_Unicode('\'');
1032 60 : }
1033 :
1034 60 : }
1035 :
1036 0 : void SdrTextObj::TakeObjNamePlural(XubString& rName) const
1037 : {
1038 0 : switch (eTextKind) {
1039 0 : case OBJ_OUTLINETEXT: rName=ImpGetResStr(STR_ObjNamePluralOUTLINETEXT); break;
1040 0 : case OBJ_TITLETEXT : rName=ImpGetResStr(STR_ObjNamePluralTITLETEXT); break;
1041 : default: {
1042 0 : if (IsLinkedText()) {
1043 0 : rName=ImpGetResStr(STR_ObjNamePluralTEXTLNK);
1044 : } else {
1045 0 : rName=ImpGetResStr(STR_ObjNamePluralTEXT);
1046 : }
1047 0 : } break;
1048 : } // switch
1049 0 : }
1050 :
1051 0 : SdrTextObj* SdrTextObj::Clone() const
1052 : {
1053 0 : return CloneHelper< SdrTextObj >();
1054 : }
1055 :
1056 10 : SdrTextObj& SdrTextObj::operator=(const SdrTextObj& rObj)
1057 : {
1058 10 : if( this == &rObj )
1059 0 : return *this;
1060 : // call parent
1061 10 : SdrObject::operator=(rObj);
1062 :
1063 10 : aRect =rObj.aRect;
1064 10 : aGeo =rObj.aGeo;
1065 10 : eTextKind =rObj.eTextKind;
1066 10 : bTextFrame=rObj.bTextFrame;
1067 10 : aTextSize=rObj.aTextSize;
1068 10 : bTextSizeDirty=rObj.bTextSizeDirty;
1069 :
1070 : // Not all of the necessary parameters were copied yet.
1071 10 : bNoShear = rObj.bNoShear;
1072 10 : bNoRotate = rObj.bNoRotate;
1073 10 : bNoMirror = rObj.bNoMirror;
1074 10 : bDisableAutoWidthOnDragging = rObj.bDisableAutoWidthOnDragging;
1075 :
1076 10 : OutlinerParaObject* pNewOutlinerParaObject = 0;
1077 :
1078 10 : SdrText* pText = getActiveText();
1079 :
1080 10 : if( pText && rObj.HasText() )
1081 : {
1082 6 : const Outliner* pEO=rObj.pEdtOutl;
1083 6 : if (pEO!=NULL)
1084 : {
1085 0 : pNewOutlinerParaObject = pEO->CreateParaObject();
1086 : }
1087 : else
1088 : {
1089 6 : pNewOutlinerParaObject = new OutlinerParaObject(*rObj.getActiveText()->GetOutlinerParaObject());
1090 : }
1091 : }
1092 :
1093 10 : mpText->SetOutlinerParaObject( pNewOutlinerParaObject );
1094 10 : ImpSetTextStyleSheetListeners();
1095 10 : return *this;
1096 : }
1097 :
1098 0 : basegfx::B2DPolyPolygon SdrTextObj::TakeXorPoly() const
1099 : {
1100 0 : Polygon aPol(aRect);
1101 0 : if (aGeo.nShearWink!=0) ShearPoly(aPol,aRect.TopLeft(),aGeo.nTan);
1102 0 : if (aGeo.nDrehWink!=0) RotatePoly(aPol,aRect.TopLeft(),aGeo.nSin,aGeo.nCos);
1103 :
1104 0 : basegfx::B2DPolyPolygon aRetval;
1105 0 : aRetval.append(aPol.getB2DPolygon());
1106 0 : return aRetval;
1107 : }
1108 :
1109 0 : basegfx::B2DPolyPolygon SdrTextObj::TakeContour() const
1110 : {
1111 0 : basegfx::B2DPolyPolygon aRetval(SdrAttrObj::TakeContour());
1112 :
1113 : // and now add the BoundRect of the text, if necessary
1114 0 : if ( pModel && GetOutlinerParaObject() && !IsFontwork() && !IsContourTextFrame() )
1115 : {
1116 : // using Clone()-Paint() strategy inside TakeContour() leaves a destroyed
1117 : // SdrObject as pointer in DrawOutliner. Set *this again in fetching the outliner
1118 : // in every case
1119 0 : SdrOutliner& rOutliner=ImpGetDrawOutliner();
1120 :
1121 0 : Rectangle aAnchor2;
1122 0 : Rectangle aR;
1123 0 : TakeTextRect(rOutliner,aR,sal_False,&aAnchor2);
1124 0 : rOutliner.Clear();
1125 0 : bool bFitToSize(IsFitToSize());
1126 0 : if (bFitToSize) aR=aAnchor2;
1127 0 : Polygon aPol(aR);
1128 0 : if (aGeo.nDrehWink!=0) RotatePoly(aPol,aR.TopLeft(),aGeo.nSin,aGeo.nCos);
1129 :
1130 0 : aRetval.append(aPol.getB2DPolygon());
1131 : }
1132 :
1133 0 : return aRetval;
1134 : }
1135 :
1136 26687 : void SdrTextObj::RecalcSnapRect()
1137 : {
1138 26687 : if (aGeo.nDrehWink!=0 || aGeo.nShearWink!=0) {
1139 264 : Polygon aPol(aRect);
1140 264 : if (aGeo.nShearWink!=0) ShearPoly(aPol,aRect.TopLeft(),aGeo.nTan);
1141 264 : if (aGeo.nDrehWink!=0) RotatePoly(aPol,aRect.TopLeft(),aGeo.nSin,aGeo.nCos);
1142 264 : maSnapRect=aPol.GetBoundRect();
1143 : } else {
1144 26423 : maSnapRect=aRect;
1145 : }
1146 26687 : }
1147 :
1148 0 : sal_uInt32 SdrTextObj::GetSnapPointCount() const
1149 : {
1150 0 : return 4L;
1151 : }
1152 :
1153 0 : Point SdrTextObj::GetSnapPoint(sal_uInt32 i) const
1154 : {
1155 0 : Point aP;
1156 0 : switch (i) {
1157 0 : case 0: aP=aRect.TopLeft(); break;
1158 0 : case 1: aP=aRect.TopRight(); break;
1159 0 : case 2: aP=aRect.BottomLeft(); break;
1160 0 : case 3: aP=aRect.BottomRight(); break;
1161 0 : default: aP=aRect.Center(); break;
1162 : }
1163 0 : if (aGeo.nShearWink!=0) ShearPoint(aP,aRect.TopLeft(),aGeo.nTan);
1164 0 : if (aGeo.nDrehWink!=0) RotatePoint(aP,aRect.TopLeft(),aGeo.nSin,aGeo.nCos);
1165 0 : return aP;
1166 : }
1167 :
1168 29357 : void SdrTextObj::ImpCheckMasterCachable()
1169 : {
1170 29357 : bNotMasterCachable=sal_False;
1171 :
1172 29357 : OutlinerParaObject* pOutlinerParaObject = GetOutlinerParaObject();
1173 :
1174 29357 : if(!bNotVisibleAsMaster && pOutlinerParaObject && pOutlinerParaObject->IsEditDoc() )
1175 : {
1176 28623 : const EditTextObject& rText= pOutlinerParaObject->GetTextObject();
1177 28623 : bNotMasterCachable=rText.HasField(SvxPageField::StaticClassId());
1178 28623 : if( !bNotMasterCachable )
1179 : {
1180 28287 : bNotMasterCachable=rText.HasField(SvxHeaderField::StaticClassId());
1181 28287 : if( !bNotMasterCachable )
1182 : {
1183 28107 : bNotMasterCachable=rText.HasField(SvxFooterField::StaticClassId());
1184 28107 : if( !bNotMasterCachable )
1185 : {
1186 27794 : bNotMasterCachable=rText.HasField(SvxDateTimeField::StaticClassId());
1187 : }
1188 : }
1189 : }
1190 : }
1191 29357 : }
1192 :
1193 : // Extracted from ImpGetDrawOutliner()
1194 262521 : void SdrTextObj::ImpInitDrawOutliner( SdrOutliner& rOutl ) const
1195 : {
1196 262521 : rOutl.SetUpdateMode(sal_False);
1197 262521 : sal_uInt16 nOutlinerMode = OUTLINERMODE_OUTLINEOBJECT;
1198 262521 : if ( !IsOutlText() )
1199 260428 : nOutlinerMode = OUTLINERMODE_TEXTOBJECT;
1200 262521 : rOutl.Init( nOutlinerMode );
1201 :
1202 262521 : rOutl.SetGlobalCharStretching(100,100);
1203 262521 : sal_uIntPtr nStat=rOutl.GetControlWord();
1204 262521 : nStat&=~(EE_CNTRL_STRETCHING|EE_CNTRL_AUTOPAGESIZE);
1205 262521 : rOutl.SetControlWord(nStat);
1206 262521 : Size aNullSize;
1207 262521 : Size aMaxSize(100000,100000);
1208 262521 : rOutl.SetMinAutoPaperSize(aNullSize);
1209 262521 : rOutl.SetMaxAutoPaperSize(aMaxSize);
1210 262521 : rOutl.SetPaperSize(aMaxSize);
1211 262521 : rOutl.ClearPolygon();
1212 262521 : }
1213 :
1214 262521 : SdrOutliner& SdrTextObj::ImpGetDrawOutliner() const
1215 : {
1216 262521 : SdrOutliner& rOutl=pModel->GetDrawOutliner(this);
1217 :
1218 : // Code extracted to ImpInitDrawOutliner()
1219 262521 : ImpInitDrawOutliner( rOutl );
1220 :
1221 262521 : return rOutl;
1222 : }
1223 :
1224 : // Extracted from Paint()
1225 0 : void SdrTextObj::ImpSetupDrawOutlinerForPaint( bool bContourFrame,
1226 : SdrOutliner& rOutliner,
1227 : Rectangle& rTextRect,
1228 : Rectangle& rAnchorRect,
1229 : Rectangle& rPaintRect,
1230 : Fraction& rFitXKorreg ) const
1231 : {
1232 0 : if (!bContourFrame)
1233 : {
1234 : // FitToSize can't be used together with ContourFrame for now
1235 0 : if (IsFitToSize() || IsAutoFit())
1236 : {
1237 0 : sal_uIntPtr nStat=rOutliner.GetControlWord();
1238 0 : nStat|=EE_CNTRL_STRETCHING|EE_CNTRL_AUTOPAGESIZE;
1239 0 : rOutliner.SetControlWord(nStat);
1240 : }
1241 : }
1242 0 : rOutliner.SetFixedCellHeight(((const SdrTextFixedCellHeightItem&)GetMergedItem(SDRATTR_TEXT_USEFIXEDCELLHEIGHT)).GetValue());
1243 0 : TakeTextRect(rOutliner, rTextRect, sal_False, &rAnchorRect);
1244 0 : rPaintRect = rTextRect;
1245 :
1246 0 : if (!bContourFrame)
1247 : {
1248 : // FitToSize can't be used together with ContourFrame for now
1249 0 : if (IsFitToSize())
1250 : {
1251 0 : ImpSetCharStretching(rOutliner,rTextRect.GetSize(),rAnchorRect.GetSize(),rFitXKorreg);
1252 0 : rPaintRect=rAnchorRect;
1253 : }
1254 0 : else if (IsAutoFit())
1255 : {
1256 0 : ImpAutoFitText(rOutliner);
1257 : }
1258 : }
1259 0 : }
1260 :
1261 0 : void SdrTextObj::ImpAutoFitText( SdrOutliner& rOutliner ) const
1262 : {
1263 0 : const Size aShapeSize=GetSnapRect().GetSize();
1264 : ImpAutoFitText( rOutliner,
1265 0 : Size(aShapeSize.Width()-GetTextLeftDistance()-GetTextRightDistance(),
1266 0 : aShapeSize.Height()-GetTextUpperDistance()-GetTextLowerDistance()),
1267 0 : IsVerticalWriting() );
1268 0 : }
1269 :
1270 17 : void SdrTextObj::ImpAutoFitText( SdrOutliner& rOutliner, const Size& rTextSize, bool bIsVerticalWriting )
1271 : {
1272 : // EditEngine formatting is unstable enough for
1273 : // line-breaking text that we need some more samples
1274 :
1275 : // loop early-exits if we detect an already attained value
1276 17 : sal_uInt16 nMinStretchX=0, nMinStretchY=0;
1277 17 : sal_uInt16 aOldStretchXVals[]={0,0,0,0,0,0,0,0,0,0};
1278 17 : const size_t aStretchArySize=SAL_N_ELEMENTS(aOldStretchXVals);
1279 34 : for(unsigned int i=0; i<aStretchArySize; ++i)
1280 : {
1281 34 : const Size aCurrTextSize = rOutliner.CalcTextSizeNTP();
1282 34 : double fFactor(1.0);
1283 34 : if( bIsVerticalWriting )
1284 0 : fFactor = double(rTextSize.Width())/aCurrTextSize.Width();
1285 : else
1286 34 : fFactor = double(rTextSize.Height())/aCurrTextSize.Height();
1287 : // fFactor scales in both x and y directions
1288 : // - this is fine for bulleted words
1289 : // - but it scales too much for a long paragraph
1290 : // - taking sqrt scales long paragraphs the best
1291 : // - bulleted words will have to go through more iterations
1292 34 : fFactor = std::sqrt(fFactor);
1293 :
1294 : sal_uInt16 nCurrStretchX, nCurrStretchY;
1295 34 : rOutliner.GetGlobalCharStretching(nCurrStretchX, nCurrStretchY);
1296 :
1297 34 : if (fFactor >= 1.0 )
1298 : {
1299 : // resulting text area fits into available shape rect -
1300 : // err on the larger stretching, to optimally fill area
1301 34 : nMinStretchX = std::max(nMinStretchX,nCurrStretchX);
1302 34 : nMinStretchY = std::max(nMinStretchY,nCurrStretchY);
1303 : }
1304 :
1305 34 : aOldStretchXVals[i] = nCurrStretchX;
1306 34 : if( std::find(aOldStretchXVals, aOldStretchXVals+i, nCurrStretchX) != aOldStretchXVals+i )
1307 17 : break; // same value already attained once; algo is looping, exit
1308 :
1309 17 : if (fFactor < 1.0 || (fFactor >= 1.0 && nCurrStretchX != 100))
1310 : {
1311 0 : nCurrStretchX = sal::static_int_cast<sal_uInt16>(nCurrStretchX*fFactor);
1312 0 : nCurrStretchY = sal::static_int_cast<sal_uInt16>(nCurrStretchY*fFactor);
1313 0 : rOutliner.SetGlobalCharStretching(std::min(sal_uInt16(100),nCurrStretchX),
1314 0 : std::min(sal_uInt16(100),nCurrStretchY));
1315 : OSL_TRACE("SdrTextObj::onEditOutlinerStatusEvent(): zoom is %d", nCurrStretchX);
1316 : }
1317 : }
1318 :
1319 : OSL_TRACE("---- SdrTextObj::onEditOutlinerStatusEvent(): final zoom is %d ----", nMinStretchX);
1320 34 : rOutliner.SetGlobalCharStretching(std::min(sal_uInt16(100),nMinStretchX),
1321 51 : std::min(sal_uInt16(100),nMinStretchY));
1322 17 : }
1323 :
1324 0 : void SdrTextObj::SetupOutlinerFormatting( SdrOutliner& rOutl, Rectangle& rPaintRect ) const
1325 : {
1326 0 : ImpInitDrawOutliner( rOutl );
1327 0 : UpdateOutlinerFormatting( rOutl, rPaintRect );
1328 0 : }
1329 :
1330 0 : void SdrTextObj::UpdateOutlinerFormatting( SdrOutliner& rOutl, Rectangle& rPaintRect ) const
1331 : {
1332 0 : Rectangle aTextRect;
1333 0 : Rectangle aAnchorRect;
1334 0 : Fraction aFitXKorreg(1,1);
1335 :
1336 0 : bool bContourFrame=IsContourTextFrame();
1337 :
1338 0 : if( GetModel() )
1339 : {
1340 : MapMode aMapMode(GetModel()->GetScaleUnit(), Point(0,0),
1341 0 : GetModel()->GetScaleFraction(),
1342 0 : GetModel()->GetScaleFraction());
1343 0 : rOutl.SetRefMapMode(aMapMode);
1344 : }
1345 :
1346 0 : ImpSetupDrawOutlinerForPaint( bContourFrame, rOutl, aTextRect, aAnchorRect, rPaintRect, aFitXKorreg );
1347 0 : }
1348 :
1349 : ////////////////////////////////////////////////////////////////////////////////////////////////////
1350 :
1351 163151 : OutlinerParaObject* SdrTextObj::GetOutlinerParaObject() const
1352 : {
1353 163151 : SdrText* pText = getActiveText();
1354 163151 : if( pText )
1355 163151 : return pText->GetOutlinerParaObject();
1356 : else
1357 0 : return 0;
1358 : }
1359 :
1360 1426 : void SdrTextObj::NbcSetOutlinerParaObject(OutlinerParaObject* pTextObject)
1361 : {
1362 1426 : NbcSetOutlinerParaObjectForText( pTextObject, getActiveText() );
1363 1426 : }
1364 :
1365 29357 : void SdrTextObj::NbcSetOutlinerParaObjectForText( OutlinerParaObject* pTextObject, SdrText* pText )
1366 : {
1367 29357 : if( pText )
1368 29357 : pText->SetOutlinerParaObject( pTextObject );
1369 :
1370 29357 : if( pText->GetOutlinerParaObject() )
1371 : {
1372 29201 : SvxWritingModeItem aWritingMode(pText->GetOutlinerParaObject()->IsVertical()
1373 : ? com::sun::star::text::WritingMode_TB_RL
1374 : : com::sun::star::text::WritingMode_LR_TB,
1375 29201 : SDRATTR_TEXTDIRECTION);
1376 29201 : GetProperties().SetObjectItemDirect(aWritingMode);
1377 : }
1378 :
1379 29357 : SetTextSizeDirty();
1380 29357 : if (IsTextFrame() && (IsAutoGrowHeight() || IsAutoGrowWidth()))
1381 : { // adapt text frame!
1382 26845 : NbcAdjustTextFrameWidthAndHeight();
1383 : }
1384 29357 : if (!IsTextFrame())
1385 : {
1386 : // the SnapRect keeps its size
1387 794 : SetRectsDirty(sal_True);
1388 : }
1389 :
1390 : // always invalidate BoundRect on change
1391 29357 : SetBoundRectDirty();
1392 29357 : ActionChanged();
1393 :
1394 29357 : ImpSetTextStyleSheetListeners();
1395 29357 : ImpCheckMasterCachable();
1396 29357 : }
1397 :
1398 9 : void SdrTextObj::NbcReformatText()
1399 : {
1400 9 : SdrText* pText = getActiveText();
1401 9 : if( pText && pText->GetOutlinerParaObject() )
1402 : {
1403 1 : pText->ReformatText();
1404 1 : if (bTextFrame)
1405 : {
1406 0 : NbcAdjustTextFrameWidthAndHeight();
1407 : }
1408 : else
1409 : {
1410 : // the SnapRect keeps its size
1411 1 : SetBoundRectDirty();
1412 1 : SetRectsDirty(sal_True);
1413 : }
1414 1 : SetTextSizeDirty();
1415 1 : ActionChanged();
1416 : // i22396
1417 : // Necessary here since we have no compare operator at the outliner
1418 : // para object which may detect changes regarding the combination
1419 : // of outliner para data and configuration (e.g., change of
1420 : // formatting of text numerals)
1421 1 : GetViewContact().flushViewObjectContacts(false);
1422 : }
1423 9 : }
1424 :
1425 0 : void SdrTextObj::ReformatText()
1426 : {
1427 0 : if(GetOutlinerParaObject())
1428 : {
1429 0 : Rectangle aBoundRect0;
1430 0 : if (pUserCall!=NULL)
1431 0 : aBoundRect0=GetLastBoundRect();
1432 :
1433 0 : NbcReformatText();
1434 0 : SetChanged();
1435 0 : BroadcastObjectChange();
1436 0 : SendUserCall(SDRUSERCALL_RESIZE,aBoundRect0);
1437 : }
1438 0 : }
1439 :
1440 8 : SdrObjGeoData* SdrTextObj::NewGeoData() const
1441 : {
1442 8 : return new SdrTextObjGeoData;
1443 : }
1444 :
1445 187 : void SdrTextObj::SaveGeoData(SdrObjGeoData& rGeo) const
1446 : {
1447 187 : SdrAttrObj::SaveGeoData(rGeo);
1448 187 : SdrTextObjGeoData& rTGeo=(SdrTextObjGeoData&)rGeo;
1449 187 : rTGeo.aRect =aRect;
1450 187 : rTGeo.aGeo =aGeo;
1451 187 : }
1452 :
1453 0 : void SdrTextObj::RestGeoData(const SdrObjGeoData& rGeo)
1454 : { // RectsDirty is called by SdrObject
1455 0 : SdrAttrObj::RestGeoData(rGeo);
1456 0 : SdrTextObjGeoData& rTGeo=(SdrTextObjGeoData&)rGeo;
1457 0 : NbcSetLogicRect(rTGeo.aRect);
1458 0 : aGeo =rTGeo.aGeo;
1459 0 : SetTextSizeDirty();
1460 0 : }
1461 :
1462 101030 : SdrFitToSizeType SdrTextObj::GetFitToSize() const
1463 : {
1464 101030 : SdrFitToSizeType eType = SDRTEXTFIT_NONE;
1465 :
1466 101030 : if(!IsAutoGrowWidth())
1467 47136 : eType = ((SdrTextFitToSizeTypeItem&)(GetObjectItem(SDRATTR_TEXT_FITTOSIZE))).GetValue();
1468 :
1469 101030 : return eType;
1470 : }
1471 :
1472 692 : void SdrTextObj::ForceOutlinerParaObject()
1473 : {
1474 692 : SdrText* pText = getActiveText();
1475 692 : if( pText && (pText->GetOutlinerParaObject() == 0) )
1476 : {
1477 24 : sal_uInt16 nOutlMode = OUTLINERMODE_TEXTOBJECT;
1478 24 : if( IsTextFrame() && eTextKind == OBJ_OUTLINETEXT )
1479 0 : nOutlMode = OUTLINERMODE_OUTLINEOBJECT;
1480 :
1481 24 : pText->ForceOutlinerParaObject( nOutlMode );
1482 : }
1483 692 : }
1484 :
1485 1612 : sal_Bool SdrTextObj::IsVerticalWriting() const
1486 : {
1487 1612 : if(pEdtOutl)
1488 : {
1489 0 : return pEdtOutl->IsVertical();
1490 : }
1491 :
1492 1612 : OutlinerParaObject* pOutlinerParaObject = GetOutlinerParaObject();
1493 1612 : if(pOutlinerParaObject)
1494 : {
1495 763 : return pOutlinerParaObject->IsVertical();
1496 : }
1497 :
1498 849 : return sal_False;
1499 : }
1500 :
1501 40578 : void SdrTextObj::SetVerticalWriting(sal_Bool bVertical)
1502 : {
1503 40578 : OutlinerParaObject* pOutlinerParaObject = GetOutlinerParaObject();
1504 40578 : if( !pOutlinerParaObject && bVertical )
1505 : {
1506 : // we only need to force a outliner para object if the default of
1507 : // horizontal text is changed
1508 0 : ForceOutlinerParaObject();
1509 0 : pOutlinerParaObject = GetOutlinerParaObject();
1510 : }
1511 :
1512 40578 : if( pOutlinerParaObject && (pOutlinerParaObject->IsVertical() != (bool)bVertical) )
1513 : {
1514 : // get item settings
1515 0 : const SfxItemSet& rSet = GetObjectItemSet();
1516 0 : sal_Bool bAutoGrowWidth = ((SdrTextAutoGrowWidthItem&)rSet.Get(SDRATTR_TEXT_AUTOGROWWIDTH)).GetValue();
1517 0 : sal_Bool bAutoGrowHeight = ((SdrTextAutoGrowHeightItem&)rSet.Get(SDRATTR_TEXT_AUTOGROWHEIGHT)).GetValue();
1518 :
1519 : // Also exchange hor/ver adjust items
1520 0 : SdrTextHorzAdjust eHorz = ((SdrTextHorzAdjustItem&)(rSet.Get(SDRATTR_TEXT_HORZADJUST))).GetValue();
1521 0 : SdrTextVertAdjust eVert = ((SdrTextVertAdjustItem&)(rSet.Get(SDRATTR_TEXT_VERTADJUST))).GetValue();
1522 :
1523 : // rescue object size
1524 0 : Rectangle aObjectRect = GetSnapRect();
1525 :
1526 : // prepare ItemSet to set exchanged width and height items
1527 0 : SfxItemSet aNewSet(*rSet.GetPool(),
1528 : SDRATTR_TEXT_AUTOGROWHEIGHT, SDRATTR_TEXT_AUTOGROWHEIGHT,
1529 : // Expanded item ranges to also support hor and ver adjust.
1530 : SDRATTR_TEXT_VERTADJUST, SDRATTR_TEXT_VERTADJUST,
1531 : SDRATTR_TEXT_AUTOGROWWIDTH, SDRATTR_TEXT_HORZADJUST,
1532 0 : 0, 0);
1533 :
1534 0 : aNewSet.Put(rSet);
1535 0 : aNewSet.Put(SdrTextAutoGrowWidthItem(bAutoGrowHeight));
1536 0 : aNewSet.Put(SdrTextAutoGrowHeightItem(bAutoGrowWidth));
1537 :
1538 : // Exchange horz and vert adjusts
1539 0 : switch(eVert)
1540 : {
1541 0 : case SDRTEXTVERTADJUST_TOP: aNewSet.Put(SdrTextHorzAdjustItem(SDRTEXTHORZADJUST_RIGHT)); break;
1542 0 : case SDRTEXTVERTADJUST_CENTER: aNewSet.Put(SdrTextHorzAdjustItem(SDRTEXTHORZADJUST_CENTER)); break;
1543 0 : case SDRTEXTVERTADJUST_BOTTOM: aNewSet.Put(SdrTextHorzAdjustItem(SDRTEXTHORZADJUST_LEFT)); break;
1544 0 : case SDRTEXTVERTADJUST_BLOCK: aNewSet.Put(SdrTextHorzAdjustItem(SDRTEXTHORZADJUST_BLOCK)); break;
1545 : }
1546 0 : switch(eHorz)
1547 : {
1548 0 : case SDRTEXTHORZADJUST_LEFT: aNewSet.Put(SdrTextVertAdjustItem(SDRTEXTVERTADJUST_BOTTOM)); break;
1549 0 : case SDRTEXTHORZADJUST_CENTER: aNewSet.Put(SdrTextVertAdjustItem(SDRTEXTVERTADJUST_CENTER)); break;
1550 0 : case SDRTEXTHORZADJUST_RIGHT: aNewSet.Put(SdrTextVertAdjustItem(SDRTEXTVERTADJUST_TOP)); break;
1551 0 : case SDRTEXTHORZADJUST_BLOCK: aNewSet.Put(SdrTextVertAdjustItem(SDRTEXTVERTADJUST_BLOCK)); break;
1552 : }
1553 :
1554 0 : SetObjectItemSet(aNewSet);
1555 :
1556 0 : pOutlinerParaObject = GetOutlinerParaObject();
1557 0 : if( pOutlinerParaObject )
1558 : {
1559 : // set ParaObject orientation accordingly
1560 0 : pOutlinerParaObject->SetVertical(bVertical);
1561 : }
1562 :
1563 : // restore object size
1564 0 : SetSnapRect(aObjectRect);
1565 : }
1566 40578 : }
1567 :
1568 : ////////////////////////////////////////////////////////////////////////////////////////////////////
1569 : //
1570 : // transformation interface for StarOfficeAPI. This implements support for
1571 : // homogeneous 3x3 matrices containing the transformation of the SdrObject. At the
1572 : // moment it contains a shearX, rotation and translation, but for setting all linear
1573 : // transforms like Scale, ShearX, ShearY, Rotate and Translate are supported.
1574 : //
1575 : ////////////////////////////////////////////////////////////////////////////////////////////////////
1576 : // gets base transformation and rectangle of object. If it's an SdrPathObj it fills the PolyPolygon
1577 : // with the base geometry and returns TRUE. Otherwise it returns FALSE.
1578 16086 : sal_Bool SdrTextObj::TRGetBaseGeometry(basegfx::B2DHomMatrix& rMatrix, basegfx::B2DPolyPolygon& /*rPolyPolygon*/) const
1579 : {
1580 : // get turn and shear
1581 16086 : double fRotate = (aGeo.nDrehWink / 100.0) * F_PI180;
1582 16086 : double fShearX = (aGeo.nShearWink / 100.0) * F_PI180;
1583 :
1584 : // get aRect, this is the unrotated snaprect
1585 16086 : Rectangle aRectangle(aRect);
1586 :
1587 : // fill other values
1588 16086 : basegfx::B2DTuple aScale(aRectangle.GetWidth(), aRectangle.GetHeight());
1589 32172 : basegfx::B2DTuple aTranslate(aRectangle.Left(), aRectangle.Top());
1590 :
1591 : // position maybe relative to anchorpos, convert
1592 16086 : if( pModel && pModel->IsWriter() )
1593 : {
1594 22 : if(GetAnchorPos().X() || GetAnchorPos().Y())
1595 : {
1596 0 : aTranslate -= basegfx::B2DTuple(GetAnchorPos().X(), GetAnchorPos().Y());
1597 : }
1598 : }
1599 :
1600 : // force MapUnit to 100th mm
1601 16086 : const SfxMapUnit eMapUnit(GetObjectMapUnit());
1602 16086 : if(eMapUnit != SFX_MAPUNIT_100TH_MM)
1603 : {
1604 22 : switch(eMapUnit)
1605 : {
1606 : case SFX_MAPUNIT_TWIP :
1607 : {
1608 : // postion
1609 22 : aTranslate.setX(ImplTwipsToMM(aTranslate.getX()));
1610 22 : aTranslate.setY(ImplTwipsToMM(aTranslate.getY()));
1611 :
1612 : // size
1613 22 : aScale.setX(ImplTwipsToMM(aScale.getX()));
1614 22 : aScale.setY(ImplTwipsToMM(aScale.getY()));
1615 :
1616 22 : break;
1617 : }
1618 : default:
1619 : {
1620 : OSL_FAIL("TRGetBaseGeometry: Missing unit translation to 100th mm!");
1621 : }
1622 : }
1623 : }
1624 :
1625 : // build matrix
1626 48258 : rMatrix = basegfx::tools::createScaleShearXRotateTranslateB2DHomMatrix(
1627 : aScale,
1628 16086 : basegfx::fTools::equalZero(fShearX) ? 0.0 : tan(fShearX),
1629 16086 : basegfx::fTools::equalZero(fRotate) ? 0.0 : -fRotate,
1630 16086 : aTranslate);
1631 :
1632 32172 : return sal_False;
1633 : }
1634 :
1635 : // sets the base geometry of the object using infos contained in the homogeneous 3x3 matrix.
1636 : // If it's an SdrPathObj it will use the provided geometry information. The Polygon has
1637 : // to use (0,0) as upper left and will be scaled to the given size in the matrix.
1638 15950 : void SdrTextObj::TRSetBaseGeometry(const basegfx::B2DHomMatrix& rMatrix, const basegfx::B2DPolyPolygon& /*rPolyPolygon*/)
1639 : {
1640 : // break up matrix
1641 15950 : basegfx::B2DTuple aScale;
1642 31900 : basegfx::B2DTuple aTranslate;
1643 15950 : double fRotate(0.0);
1644 15950 : double fShearX(0.0);
1645 15950 : rMatrix.decompose(aScale, aTranslate, fRotate, fShearX);
1646 :
1647 : // #i75086# Old DrawingLayer (GeoStat and geometry) does not support holding negative scalings
1648 : // in X and Y which equal a 180 degree rotation. Recognize it and react accordingly
1649 15950 : if(basegfx::fTools::less(aScale.getX(), 0.0) && basegfx::fTools::less(aScale.getY(), 0.0))
1650 : {
1651 0 : aScale.setX(fabs(aScale.getX()));
1652 0 : aScale.setY(fabs(aScale.getY()));
1653 0 : fRotate = fmod(fRotate + F_PI, F_2PI);
1654 : }
1655 :
1656 : // reset object shear and rotations
1657 15950 : aGeo.nDrehWink = 0;
1658 15950 : aGeo.RecalcSinCos();
1659 15950 : aGeo.nShearWink = 0;
1660 15950 : aGeo.RecalcTan();
1661 :
1662 : // force metric to pool metric
1663 15950 : const SfxMapUnit eMapUnit(GetObjectMapUnit());
1664 15950 : if(eMapUnit != SFX_MAPUNIT_100TH_MM)
1665 : {
1666 22 : switch(eMapUnit)
1667 : {
1668 : case SFX_MAPUNIT_TWIP :
1669 : {
1670 : // position
1671 22 : aTranslate.setX(ImplMMToTwips(aTranslate.getX()));
1672 22 : aTranslate.setY(ImplMMToTwips(aTranslate.getY()));
1673 :
1674 : // size
1675 22 : aScale.setX(ImplMMToTwips(aScale.getX()));
1676 22 : aScale.setY(ImplMMToTwips(aScale.getY()));
1677 :
1678 22 : break;
1679 : }
1680 : default:
1681 : {
1682 : OSL_FAIL("TRSetBaseGeometry: Missing unit translation to PoolMetric!");
1683 : }
1684 : }
1685 : }
1686 :
1687 : // if anchor is used, make position relative to it
1688 15950 : if( pModel && pModel->IsWriter() )
1689 : {
1690 22 : if(GetAnchorPos().X() || GetAnchorPos().Y())
1691 : {
1692 0 : aTranslate += basegfx::B2DTuple(GetAnchorPos().X(), GetAnchorPos().Y());
1693 : }
1694 : }
1695 :
1696 : // build and set BaseRect (use scale)
1697 15950 : Point aPoint = Point();
1698 15950 : Size aSize(FRound(aScale.getX()), FRound(aScale.getY()));
1699 15950 : Rectangle aBaseRect(aPoint, aSize);
1700 15950 : SetSnapRect(aBaseRect);
1701 :
1702 : // shear?
1703 15950 : if(!basegfx::fTools::equalZero(fShearX))
1704 : {
1705 0 : GeoStat aGeoStat;
1706 0 : aGeoStat.nShearWink = FRound((atan(fShearX) / F_PI180) * 100.0);
1707 0 : aGeoStat.RecalcTan();
1708 0 : Shear(Point(), aGeoStat.nShearWink, aGeoStat.nTan, sal_False);
1709 : }
1710 :
1711 : // rotation?
1712 15950 : if(!basegfx::fTools::equalZero(fRotate))
1713 : {
1714 382 : GeoStat aGeoStat;
1715 :
1716 : // #i78696#
1717 : // fRotate is matematically correct, but aGeoStat.nDrehWink is
1718 : // mirrored -> mirror value here
1719 382 : aGeoStat.nDrehWink = NormAngle360(FRound(-fRotate / F_PI18000));
1720 382 : aGeoStat.RecalcSinCos();
1721 382 : Rotate(Point(), aGeoStat.nDrehWink, aGeoStat.nSin, aGeoStat.nCos);
1722 : }
1723 :
1724 : // translate?
1725 15950 : if(!aTranslate.equalZero())
1726 : {
1727 15485 : Move(Size(FRound(aTranslate.getX()), FRound(aTranslate.getY())));
1728 15950 : }
1729 15950 : }
1730 :
1731 0 : bool SdrTextObj::IsRealyEdited() const
1732 : {
1733 0 : return pEdtOutl && pEdtOutl->IsModified();
1734 : }
1735 :
1736 : /////////////////////////////////////////////////////////////////////////////////////////////////
1737 : // moved inlines here form hxx
1738 :
1739 25665 : long SdrTextObj::GetEckenradius() const
1740 : {
1741 25665 : return ((SdrEckenradiusItem&)(GetObjectItemSet().Get(SDRATTR_ECKENRADIUS))).GetValue();
1742 : }
1743 :
1744 68922 : long SdrTextObj::GetMinTextFrameHeight() const
1745 : {
1746 68922 : return ((SdrTextMinFrameHeightItem&)(GetObjectItemSet().Get(SDRATTR_TEXT_MINFRAMEHEIGHT))).GetValue();
1747 : }
1748 :
1749 68922 : long SdrTextObj::GetMaxTextFrameHeight() const
1750 : {
1751 68922 : return ((SdrTextMaxFrameHeightItem&)(GetObjectItemSet().Get(SDRATTR_TEXT_MAXFRAMEHEIGHT))).GetValue();
1752 : }
1753 :
1754 29923 : long SdrTextObj::GetMinTextFrameWidth() const
1755 : {
1756 29923 : return ((SdrTextMinFrameWidthItem&)(GetObjectItemSet().Get(SDRATTR_TEXT_MINFRAMEWIDTH))).GetValue();
1757 : }
1758 :
1759 29923 : long SdrTextObj::GetMaxTextFrameWidth() const
1760 : {
1761 29923 : return ((SdrTextMaxFrameWidthItem&)(GetObjectItemSet().Get(SDRATTR_TEXT_MAXFRAMEWIDTH))).GetValue();
1762 : }
1763 :
1764 34 : bool SdrTextObj::IsFontwork() const
1765 : {
1766 : return (bTextFrame) ? false // Default is FALSE
1767 34 : : ((XFormTextStyleItem&)(GetObjectItemSet().Get(XATTR_FORMTXTSTYLE))).GetValue()!=XFT_NONE;
1768 : }
1769 :
1770 0 : bool SdrTextObj::IsHideContour() const
1771 : {
1772 : return (bTextFrame) ? false // Default is: no, don't HideContour; HideContour not together with TextFrames
1773 0 : : ((XFormTextHideFormItem&)(GetObjectItemSet().Get(XATTR_FORMTXTHIDEFORM))).GetValue();
1774 : }
1775 :
1776 118433 : bool SdrTextObj::IsContourTextFrame() const
1777 : {
1778 : return (bTextFrame) ? false // ContourFrame not together with normal TextFrames
1779 118433 : : ((SdrTextContourFrameItem&)(GetObjectItemSet().Get(SDRATTR_TEXT_CONTOURFRAME))).GetValue();
1780 : }
1781 :
1782 164643 : long SdrTextObj::GetTextLeftDistance() const
1783 : {
1784 164643 : return ((SdrTextLeftDistItem&)(GetObjectItemSet().Get(SDRATTR_TEXT_LEFTDIST))).GetValue();
1785 : }
1786 :
1787 164643 : long SdrTextObj::GetTextRightDistance() const
1788 : {
1789 164643 : return ((SdrTextRightDistItem&)(GetObjectItemSet().Get(SDRATTR_TEXT_RIGHTDIST))).GetValue();
1790 : }
1791 :
1792 164643 : long SdrTextObj::GetTextUpperDistance() const
1793 : {
1794 164643 : return ((SdrTextUpperDistItem&)(GetObjectItemSet().Get(SDRATTR_TEXT_UPPERDIST))).GetValue();
1795 : }
1796 :
1797 164643 : long SdrTextObj::GetTextLowerDistance() const
1798 : {
1799 164643 : return ((SdrTextLowerDistItem&)(GetObjectItemSet().Get(SDRATTR_TEXT_LOWERDIST))).GetValue();
1800 : }
1801 :
1802 387481 : SdrTextAniKind SdrTextObj::GetTextAniKind() const
1803 : {
1804 387481 : return ((SdrTextAniKindItem&)(GetObjectItemSet().Get(SDRATTR_TEXT_ANIKIND))).GetValue();
1805 : }
1806 :
1807 73653 : SdrTextAniDirection SdrTextObj::GetTextAniDirection() const
1808 : {
1809 73653 : return ((SdrTextAniDirectionItem&)(GetObjectItemSet().Get(SDRATTR_TEXT_ANIDIRECTION))).GetValue();
1810 : }
1811 :
1812 : // Get necessary data for text scroll animation. ATM base it on a Text-Metafile and a
1813 : // painting rectangle. Rotation is excluded from the returned values.
1814 0 : GDIMetaFile* SdrTextObj::GetTextScrollMetaFileAndRectangle(
1815 : Rectangle& rScrollRectangle, Rectangle& rPaintRectangle)
1816 : {
1817 0 : GDIMetaFile* pRetval = 0L;
1818 0 : SdrOutliner& rOutliner = ImpGetDrawOutliner();
1819 0 : Rectangle aTextRect;
1820 0 : Rectangle aAnchorRect;
1821 0 : Rectangle aPaintRect;
1822 0 : Fraction aFitXKorreg(1,1);
1823 0 : bool bContourFrame(IsContourTextFrame());
1824 :
1825 : // get outliner set up. To avoid getting a somehow rotated MetaFile,
1826 : // temporarily disable object rotation.
1827 0 : sal_Int32 nAngle(aGeo.nDrehWink);
1828 0 : aGeo.nDrehWink = 0L;
1829 0 : ImpSetupDrawOutlinerForPaint( bContourFrame, rOutliner, aTextRect, aAnchorRect, aPaintRect, aFitXKorreg );
1830 0 : aGeo.nDrehWink = nAngle;
1831 :
1832 0 : Rectangle aScrollFrameRect(aPaintRect);
1833 0 : const SfxItemSet& rSet = GetObjectItemSet();
1834 0 : SdrTextAniDirection eDirection = ((SdrTextAniDirectionItem&)(rSet.Get(SDRATTR_TEXT_ANIDIRECTION))).GetValue();
1835 :
1836 0 : if(SDRTEXTANI_LEFT == eDirection || SDRTEXTANI_RIGHT == eDirection)
1837 : {
1838 0 : aScrollFrameRect.Left() = aAnchorRect.Left();
1839 0 : aScrollFrameRect.Right() = aAnchorRect.Right();
1840 : }
1841 :
1842 0 : if(SDRTEXTANI_UP == eDirection || SDRTEXTANI_DOWN == eDirection)
1843 : {
1844 0 : aScrollFrameRect.Top() = aAnchorRect.Top();
1845 0 : aScrollFrameRect.Bottom() = aAnchorRect.Bottom();
1846 : }
1847 :
1848 : // create the MetaFile
1849 0 : pRetval = new GDIMetaFile;
1850 0 : VirtualDevice aBlackHole;
1851 0 : aBlackHole.EnableOutput(sal_False);
1852 0 : pRetval->Record(&aBlackHole);
1853 0 : Point aPaintPos = aPaintRect.TopLeft();
1854 :
1855 0 : rOutliner.Draw(&aBlackHole, aPaintPos);
1856 :
1857 0 : pRetval->Stop();
1858 0 : pRetval->WindStart();
1859 :
1860 : // return PaintRectanglePixel and pRetval;
1861 0 : rScrollRectangle = aScrollFrameRect;
1862 0 : rPaintRectangle = aPaintRect;
1863 :
1864 0 : return pRetval;
1865 : }
1866 :
1867 : // Access to TextAnimationAllowed flag
1868 13689 : bool SdrTextObj::IsAutoFit() const
1869 : {
1870 13689 : return GetFitToSize()==SDRTEXTFIT_AUTOFIT;
1871 : }
1872 :
1873 87341 : bool SdrTextObj::IsFitToSize() const
1874 : {
1875 87341 : const SdrFitToSizeType eFit=GetFitToSize();
1876 87341 : return (eFit==SDRTEXTFIT_PROPORTIONAL || eFit==SDRTEXTFIT_ALLLINES);
1877 : }
1878 :
1879 0 : void SdrTextObj::SetTextAnimationAllowed(sal_Bool bNew)
1880 : {
1881 0 : if(mbTextAnimationAllowed != bNew)
1882 : {
1883 0 : mbTextAnimationAllowed = bNew;
1884 0 : ActionChanged();
1885 : }
1886 0 : }
1887 :
1888 : /** called from the SdrObjEditView during text edit when the status of the edit outliner changes */
1889 0 : void SdrTextObj::onEditOutlinerStatusEvent( EditStatus* pEditStatus )
1890 : {
1891 0 : const sal_uInt32 nStat = pEditStatus->GetStatusWord();
1892 0 : const bool bGrowX=(nStat & EE_STAT_TEXTWIDTHCHANGED) !=0;
1893 0 : const bool bGrowY=(nStat & EE_STAT_TEXTHEIGHTCHANGED) !=0;
1894 0 : if(bTextFrame && (bGrowX || bGrowY))
1895 : {
1896 0 : if ((bGrowX && IsAutoGrowWidth()) || (bGrowY && IsAutoGrowHeight()))
1897 : {
1898 0 : AdjustTextFrameWidthAndHeight();
1899 : }
1900 0 : else if (IsAutoFit() && !mbInDownScale)
1901 : {
1902 : OSL_ASSERT(pEdtOutl);
1903 0 : mbInDownScale = sal_True;
1904 :
1905 : // sucks that we cannot disable paints via
1906 : // pEdtOutl->SetUpdateMode(FALSE) - but EditEngine skips
1907 : // formatting as well, then.
1908 0 : ImpAutoFitText(*pEdtOutl);
1909 0 : mbInDownScale = sal_False;
1910 : }
1911 : }
1912 0 : }
1913 :
1914 : /** returns the currently active text. */
1915 177650 : SdrText* SdrTextObj::getActiveText() const
1916 : {
1917 177650 : if( !mpText )
1918 84 : return getText( 0 );
1919 : else
1920 177566 : return mpText;
1921 : }
1922 :
1923 : /** returns the nth available text. */
1924 236657 : SdrText* SdrTextObj::getText( sal_Int32 nIndex ) const
1925 : {
1926 236657 : if( nIndex == 0 )
1927 : {
1928 236657 : if( mpText == 0 )
1929 30751 : const_cast< SdrTextObj* >(this)->mpText = new SdrText( *(const_cast< SdrTextObj* >(this)) );
1930 236657 : return mpText;
1931 : }
1932 : else
1933 : {
1934 0 : return 0;
1935 : }
1936 : }
1937 :
1938 : /** returns the number of texts available for this object. */
1939 163916 : sal_Int32 SdrTextObj::getTextCount() const
1940 : {
1941 163916 : return 1;
1942 : }
1943 :
1944 : /** changes the current active text */
1945 0 : void SdrTextObj::setActiveText( sal_Int32 /*nIndex*/ )
1946 : {
1947 0 : }
1948 :
1949 : /** returns the index of the text that contains the given point or -1 */
1950 0 : sal_Int32 SdrTextObj::CheckTextHit(const Point& /*rPnt*/) const
1951 : {
1952 0 : return 0;
1953 : }
1954 :
1955 0 : void SdrTextObj::SetObjectItemNoBroadcast(const SfxPoolItem& rItem)
1956 : {
1957 0 : static_cast< sdr::properties::TextProperties& >(GetProperties()).SetObjectItemNoBroadcast(rItem);
1958 258 : }
1959 :
1960 : /////////////////////////////////////////////////////////////////////////////////////////////////
1961 : //
1962 : // The concept of the text object:
1963 : // ~~~~~~~~~~~~~~~~~~~~~~~~
1964 : // Attributes/Variations:
1965 : // - sal_Bool text frame / graphics object with caption
1966 : // - sal_Bool FontWork (if it is not a text frame and not a ContourTextFrame)
1967 : // - sal_Bool ContourTextFrame (if it is not a text frame and not Fontwork)
1968 : // - long rotation angle (if it is not FontWork)
1969 : // - long text frame margins (if it is not FontWork)
1970 : // - sal_Bool FitToSize (if it is not FontWork)
1971 : // - sal_Bool AutoGrowingWidth/Height (if it is not FitToSize and not FontWork)
1972 : // - long Min/MaxFrameWidth/Height (if AutoGrowingWidth/Height)
1973 : // - enum horizontal text anchoring left,center,right,justify/block,Stretch(ni)
1974 : // - enum vertical text anchoring top, middle, bottom, block, stretch(ni)
1975 : // - enum ticker text (if it is not FontWork)
1976 : //
1977 : // Every derived object is either a text frame (bTextFrame=sal_True)
1978 : // or a drawing object with a caption (bTextFrame=sal_False).
1979 : //
1980 : // Default anchoring for text frames:
1981 : // SDRTEXTHORZADJUST_BLOCK, SDRTEXTVERTADJUST_TOP
1982 : // = static Pool defaults
1983 : // Default anchoring for drawing objects with a caption:
1984 : // SDRTEXTHORZADJUST_CENTER, SDRTEXTVERTADJUST_CENTER
1985 : // via "hard" attribution of SdrAttrObj
1986 : //
1987 : // Every object derived from SdrTextObj must return an "UnrotatedSnapRect"
1988 : // (->TakeUnrotatedSnapRect()) (the reference point for the rotation is the top
1989 : // left of the rectangle (aGeo.nDrehWink)) which is the basis for anchoring
1990 : // text. We then subtract the text frame margins from this rectangle, as a re-
1991 : // sult we get the anchoring area (->TakeTextAnchorRect()). Within this area, we
1992 : // calculate the anchoring point and the painting area, depending on the hori-
1993 : // zontal and vertical adjustment of the text (SdrTextVertAdjust,
1994 : // SdrTextHorzAdjust).
1995 : // In the case of drawing objects with a caption the painting area might well
1996 : // be larger than the anchoring area, for text frames on the other hand, it is
1997 : // always of the same or a smaller size (except when there are negative text
1998 : // frame margins).
1999 : //
2000 : // FitToSize takes priority over text anchoring and AutoGrowHeight/Width. When
2001 : // FitToSize is turned on, the painting area is always equal to the anchoring
2002 : // area. Additionally, FitToSize doesn't allow automatic line breaks.
2003 : //
2004 : // ContourTextFrame:
2005 : // - long rotation angle
2006 : // - long text frame margins (maybe later)
2007 : // - sal_Bool FitToSize (maybe later)
2008 : // - sal_Bool AutoGrowingWidth/Height (maybe much later)
2009 : // - long Min/MaxFrameWidth/Height (maybe much later)
2010 : // - enum horizontal text anchoring (maybe later, for now: left, centered)
2011 : // - enum vertical text anchoring (maybe later, for now: top)
2012 : // - enum ticker text (maybe later, maybe even with correct clipping)
2013 : //
2014 : // When making changes, check these:
2015 : // - Paint
2016 : // - HitTest
2017 : // - ConvertToPoly
2018 : // - Edit
2019 : // - Printing, Saving, Painting in neighboring View while editing
2020 : // - ModelChanged (e. g. through a neighboring View or rulers) while editing
2021 : // - FillColorChanged while editin
2022 : // - and many more...
2023 : //
2024 : /////////////////////////////////////////////////////////////////////////////////////////////////
2025 :
2026 : /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
|