Bug Summary

File:home/maarten/src/libreoffice/core/include/rtl/ref.hxx
Warning:line 192, column 9
Use of memory after it is freed

Annotated Source Code

Press '?' to see keyboard shortcuts

clang -cc1 -cc1 -triple x86_64-unknown-linux-gnu -analyze -disable-free -disable-llvm-verifier -discard-value-names -main-file-name svdotext.cxx -analyzer-store=region -analyzer-opt-analyze-nested-blocks -analyzer-checker=core -analyzer-checker=apiModeling -analyzer-checker=unix -analyzer-checker=deadcode -analyzer-checker=cplusplus -analyzer-checker=security.insecureAPI.UncheckedReturn -analyzer-checker=security.insecureAPI.getpw -analyzer-checker=security.insecureAPI.gets -analyzer-checker=security.insecureAPI.mktemp -analyzer-checker=security.insecureAPI.mkstemp -analyzer-checker=security.insecureAPI.vfork -analyzer-checker=nullability.NullPassedToNonnull -analyzer-checker=nullability.NullReturnedFromNonnull -analyzer-output plist -w -setup-static-analyzer -mrelocation-model pic -pic-level 2 -mframe-pointer=all -fmath-errno -fno-rounding-math -mconstructor-aliases -munwind-tables -target-cpu x86-64 -fno-split-dwarf-inlining -debugger-tuning=gdb -resource-dir /usr/lib64/clang/11.0.0 -isystem /usr/include/libxml2 -D BOOST_ERROR_CODE_HEADER_ONLY -D BOOST_SYSTEM_NO_DEPRECATED -D CPPU_ENV=gcc3 -D LINUX -D OSL_DEBUG_LEVEL=1 -D SAL_LOG_INFO -D SAL_LOG_WARN -D UNIX -D UNX -D X86_64 -D _PTHREADS -D _REENTRANT -D SVXCORE_DLLIMPLEMENTATION -D SYSTEM_LIBXML -D EXCEPTIONS_ON -D LIBO_INTERNAL_ONLY -I /home/maarten/src/libreoffice/core/workdir/UnpackedTarball/epoxy/include -I /home/maarten/src/libreoffice/core/workdir/UnpackedTarball/pdfium -I /home/maarten/src/libreoffice/core/workdir/UnpackedTarball/pdfium/public -D COMPONENT_BUILD -I /home/maarten/src/libreoffice/core/workdir/UnpackedTarball/icu/source -I /home/maarten/src/libreoffice/core/workdir/UnpackedTarball/icu/source/i18n -I /home/maarten/src/libreoffice/core/workdir/UnpackedTarball/icu/source/common -I /home/maarten/src/libreoffice/core/external/boost/include -I /home/maarten/src/libreoffice/core/workdir/UnpackedTarball/boost -I /home/maarten/src/libreoffice/core/svx/inc -I /home/maarten/src/libreoffice/core/svx/source/inc -I /home/maarten/src/libreoffice/core/include -I /usr/lib/jvm/java-11-openjdk-11.0.9.10-0.0.ea.fc33.x86_64/include -I /usr/lib/jvm/java-11-openjdk-11.0.9.10-0.0.ea.fc33.x86_64/include/linux -I /home/maarten/src/libreoffice/core/config_host -I /home/maarten/src/libreoffice/core/workdir/CustomTarget/officecfg/registry -I /home/maarten/src/libreoffice/core/workdir/UnoApiHeadersTarget/udkapi/normal -I /home/maarten/src/libreoffice/core/workdir/UnoApiHeadersTarget/offapi/normal -I /home/maarten/src/libreoffice/core/workdir/SdiTarget/svx/sdi -internal-isystem /usr/bin/../lib/gcc/x86_64-redhat-linux/10/../../../../include/c++/10 -internal-isystem /usr/bin/../lib/gcc/x86_64-redhat-linux/10/../../../../include/c++/10/x86_64-redhat-linux -internal-isystem /usr/bin/../lib/gcc/x86_64-redhat-linux/10/../../../../include/c++/10/backward -internal-isystem /usr/local/include -internal-isystem /usr/lib64/clang/11.0.0/include -internal-externc-isystem /include -internal-externc-isystem /usr/include -O0 -Wno-missing-braces -std=c++17 -fdeprecated-macro -fdebug-compilation-dir /home/maarten/src/libreoffice/core -ferror-limit 19 -fvisibility hidden -fvisibility-inlines-hidden -stack-protector 2 -fgnuc-version=4.2.1 -fcxx-exceptions -fexceptions -debug-info-kind=constructor -analyzer-output=html -faddrsig -o /home/maarten/tmp/wis/scan-build-libreoffice/output/report/2020-10-07-141433-9725-1 -x c++ /home/maarten/src/libreoffice/core/svx/source/svdraw/svdotext.cxx

/home/maarten/src/libreoffice/core/svx/source/svdraw/svdotext.cxx

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

/home/maarten/src/libreoffice/core/include/vcl/vclptr.hxx

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#ifndef INCLUDED_VCL_PTR_HXX
21#define INCLUDED_VCL_PTR_HXX
22
23#include <sal/config.h>
24
25#include <rtl/ref.hxx>
26
27#include <utility>
28#include <type_traits>
29
30#ifdef DBG_UTIL
31#ifndef _WIN32
32#include <vcl/vclmain.hxx>
33#endif
34#endif
35
36class VclReferenceBase;
37
38namespace vcl::detail {
39
40template<typename>
41constexpr bool isIncompleteOrDerivedFromVclReferenceBase(...) { return true; }
42
43template<typename T> constexpr bool isIncompleteOrDerivedFromVclReferenceBase(
44 int (*)[sizeof(T)])
45{ return std::is_base_of<VclReferenceBase, T>::value; }
46
47} // namespace vcl::detail
48
49/**
50 * A thin wrapper around rtl::Reference to implement the acquire and dispose semantics we want for references to vcl::Window subclasses.
51 *
52 * For more details on the design please see vcl/README.lifecycle
53 *
54 * @param reference_type must be a subclass of vcl::Window
55 */
56template <class reference_type>
57class VclPtr
58{
59 static_assert(
60 vcl::detail::isIncompleteOrDerivedFromVclReferenceBase<reference_type>(
61 nullptr),
62 "template argument type must be derived from VclReferenceBase");
63
64 ::rtl::Reference<reference_type> m_rInnerRef;
65
66public:
67 /** Constructor...
68 */
69 VclPtr()
70 : m_rInnerRef()
71 {}
72
73 /** Constructor...
74 */
75 VclPtr (reference_type * pBody)
76 : m_rInnerRef(pBody)
77 {}
78
79 /** Constructor... that doesn't take a ref.
80 */
81 VclPtr (reference_type * pBody, __sal_NoAcquire)
82 : m_rInnerRef(pBody, SAL_NO_ACQUIRE)
83 {}
84
85 /** Up-casting conversion constructor: Copies interface reference.
86
87 Does not work for up-casts to ambiguous bases. For the special case of
88 up-casting to Reference< XInterface >, see the corresponding conversion
89 operator.
90
91 @param rRef another reference
92 */
93 template< class derived_type >
94 VclPtr(
95 const VclPtr< derived_type > & rRef,
96 typename std::enable_if<
97 std::is_base_of<reference_type, derived_type>::value, int>::type
98 = 0 )
99 : m_rInnerRef( static_cast<reference_type*>(rRef) )
100 {
101 }
102
103#if defined(DBG_UTIL) && !defined(_WIN32)
104 virtual ~VclPtr()
105 {
106 assert(m_rInnerRef.get() == nullptr || vclmain::isAlive())(static_cast <bool> (m_rInnerRef.get() == nullptr || vclmain
::isAlive()) ? void (0) : __assert_fail ("m_rInnerRef.get() == nullptr || vclmain::isAlive()"
, "/home/maarten/src/libreoffice/core/include/vcl/vclptr.hxx"
, 106, __extension__ __PRETTY_FUNCTION__))
;
107 // We can be one of the intermediate counts, but if we are the last
108 // VclPtr keeping this object alive, then something forgot to call dispose().
109 assert((!m_rInnerRef.get() || m_rInnerRef->isDisposed() || m_rInnerRef->getRefCount() > 1)(static_cast <bool> ((!m_rInnerRef.get() || m_rInnerRef
->isDisposed() || m_rInnerRef->getRefCount() > 1) &&
"someone forgot to call dispose()") ? void (0) : __assert_fail
("(!m_rInnerRef.get() || m_rInnerRef->isDisposed() || m_rInnerRef->getRefCount() > 1) && \"someone forgot to call dispose()\""
, "/home/maarten/src/libreoffice/core/include/vcl/vclptr.hxx"
, 110, __extension__ __PRETTY_FUNCTION__))
110 && "someone forgot to call dispose()")(static_cast <bool> ((!m_rInnerRef.get() || m_rInnerRef
->isDisposed() || m_rInnerRef->getRefCount() > 1) &&
"someone forgot to call dispose()") ? void (0) : __assert_fail
("(!m_rInnerRef.get() || m_rInnerRef->isDisposed() || m_rInnerRef->getRefCount() > 1) && \"someone forgot to call dispose()\""
, "/home/maarten/src/libreoffice/core/include/vcl/vclptr.hxx"
, 110, __extension__ __PRETTY_FUNCTION__))
;
111 }
112 VclPtr(VclPtr const &) = default;
113 VclPtr(VclPtr &&) = default;
114 VclPtr & operator =(VclPtr const &) = default;
115 VclPtr & operator =(VclPtr &&) = default;
116#endif
117
118 /**
119 * A construction helper for VclPtr. Since VclPtr types are created
120 * with a reference-count of one - to help fit into the existing
121 * code-flow; this helps us to construct them easily.
122 *
123 * For more details on the design please see vcl/README.lifecycle
124 *
125 * @tparam reference_type must be a subclass of vcl::Window
126 */
127 template<typename... Arg> [[nodiscard]] static VclPtr< reference_type > Create(Arg &&... arg)
128 {
129 return VclPtr< reference_type >( new reference_type(std::forward<Arg>(arg)...), SAL_NO_ACQUIRE );
130 }
131
132 /** Probably most common used: handle->someBodyOp().
133 */
134 reference_type * operator->() const
135 {
136 return m_rInnerRef.get();
137 }
138
139 /** Get the body. Can be used instead of operator->().
140 I.e. handle->someBodyOp() and handle.get()->someBodyOp()
141 are the same.
142 */
143 reference_type * get() const
144 {
145 return m_rInnerRef.get();
146 }
147
148 void set(reference_type *pBody)
149 {
150 m_rInnerRef.set(pBody);
151 }
152
153 void reset(reference_type *pBody)
154 {
155 m_rInnerRef.set(pBody);
156 }
157
158 /** Up-casting copy assignment operator.
159
160 Does not work for up-casts to ambiguous bases.
161
162 @param rRef another reference
163 */
164 template<typename derived_type>
165 typename std::enable_if<
166 std::is_base_of<reference_type, derived_type>::value,
167 VclPtr &>::type
168 operator =(VclPtr<derived_type> const & rRef)
169 {
170 m_rInnerRef.set(rRef.get());
171 return *this;
172 }
173
174 VclPtr & operator =(reference_type * pBody)
175 {
176 m_rInnerRef.set(pBody);
177 return *this;
178 }
179
180 operator reference_type * () const
181 {
182 return m_rInnerRef.get();
183 }
184
185 explicit operator bool () const
186 {
187 return m_rInnerRef.get() != nullptr;
188 }
189
190 void clear()
191 {
192 m_rInnerRef.clear();
193 }
194
195 void reset()
196 {
197 m_rInnerRef.clear();
198 }
199
200 void disposeAndClear()
201 {
202 // hold it alive for the lifetime of this method
203 ::rtl::Reference<reference_type> aTmp(m_rInnerRef);
204 m_rInnerRef.clear(); // we should use some 'swap' method ideally ;-)
13
Calling 'Reference::clear'
20
Returning; memory was released
205 if (aTmp.get()) {
21
Calling 'Reference::get'
206 aTmp->disposeOnce();
207 }
208 }
209
210 /** Needed to place VclPtr's into STL collection.
211 */
212 bool operator< (const VclPtr<reference_type> & handle) const
213 {
214 return (m_rInnerRef < handle.m_rInnerRef);
215 }
216}; // class VclPtr
217
218template<typename T1, typename T2>
219inline bool operator ==(VclPtr<T1> const & p1, VclPtr<T2> const & p2) {
220 return p1.get() == p2.get();
221}
222
223template<typename T> inline bool operator ==(VclPtr<T> const & p1, T const * p2)
224{
225 return p1.get() == p2;
226}
227
228template<typename T> inline bool operator ==(VclPtr<T> const & p1, T * p2) {
229 return p1.get() == p2;
230}
231
232template<typename T> inline bool operator ==(T const * p1, VclPtr<T> const & p2)
233{
234 return p1 == p2.get();
235}
236
237template<typename T> inline bool operator ==(T * p1, VclPtr<T> const & p2) {
238 return p1 == p2.get();
239}
240
241template<typename T1, typename T2>
242inline bool operator !=(VclPtr<T1> const & p1, VclPtr<T2> const & p2) {
243 return !(p1 == p2);
244}
245
246template<typename T> inline bool operator !=(VclPtr<T> const & p1, T const * p2)
247{
248 return !(p1 == p2);
249}
250
251template<typename T> inline bool operator !=(VclPtr<T> const & p1, T * p2) {
252 return !(p1 == p2);
253}
254
255template<typename T> inline bool operator !=(T const * p1, VclPtr<T> const & p2)
256{
257 return !(p1 == p2);
258}
259
260template<typename T> inline bool operator !=(T * p1, VclPtr<T> const & p2) {
261 return !(p1 == p2);
262}
263
264/**
265 * A construction helper for a temporary VclPtr. Since VclPtr types
266 * are created with a reference-count of one - to help fit into
267 * the existing code-flow; this helps us to construct them easily.
268 * see also VclPtr::Create and ScopedVclPtr
269 *
270 * For more details on the design please see vcl/README.lifecycle
271 *
272 * @param reference_type must be a subclass of vcl::Window
273 */
274template <class reference_type>
275class SAL_WARN_UNUSED__attribute__((warn_unused)) VclPtrInstance final : public VclPtr<reference_type>
276{
277public:
278 template<typename... Arg> VclPtrInstance(Arg &&... arg)
279 : VclPtr<reference_type>( new reference_type(std::forward<Arg>(arg)...), SAL_NO_ACQUIRE )
280 {
281 }
282
283 /**
284 * Override and disallow this, to prevent people accidentally calling it and actually
285 * getting VclPtr::Create and getting a naked VclPtr<> instance
286 */
287 template<typename... Arg> static VclPtrInstance< reference_type > Create(Arg &&... ) = delete;
288};
289
290template <class reference_type>
291class ScopedVclPtr : public VclPtr<reference_type>
292{
293public:
294 /** Constructor...
295 */
296 ScopedVclPtr()
297 : VclPtr<reference_type>()
298 {}
299
300 /** Constructor
301 */
302 ScopedVclPtr (reference_type * pBody)
303 : VclPtr<reference_type>(pBody)
304 {}
305
306 /** Copy constructor...
307 */
308 ScopedVclPtr (const VclPtr<reference_type> & handle)
309 : VclPtr<reference_type>(handle)
310 {}
311
312 /**
313 Assignment that releases the last reference.
314 */
315 void disposeAndReset(reference_type *pBody)
316 {
317 if (pBody != this->get()) {
318 VclPtr<reference_type>::disposeAndClear();
319 VclPtr<reference_type>::set(pBody);
320 }
321 }
322
323 /**
324 Assignment that releases the last reference.
325 */
326 ScopedVclPtr<reference_type>& operator = (reference_type * pBody)
327 {
328 disposeAndReset(pBody);
329 return *this;
330 }
331
332 /** Up-casting conversion constructor: Copies interface reference.
333
334 Does not work for up-casts to ambiguous bases. For the special case of
335 up-casting to Reference< XInterface >, see the corresponding conversion
336 operator.
337
338 @param rRef another reference
339 */
340 template< class derived_type >
341 ScopedVclPtr(
342 const VclPtr< derived_type > & rRef,
343 typename std::enable_if<
344 std::is_base_of<reference_type, derived_type>::value, int>::type
345 = 0 )
346 : VclPtr<reference_type>( rRef )
347 {
348 }
349
350 /** Up-casting assignment operator.
351
352 Does not work for up-casts to ambiguous bases.
353
354 @param rRef another VclPtr
355 */
356 template<typename derived_type>
357 typename std::enable_if<
358 std::is_base_of<reference_type, derived_type>::value,
359 ScopedVclPtr &>::type
360 operator =(VclPtr<derived_type> const & rRef)
361 {
362 disposeAndReset(rRef.get());
363 return *this;
364 }
365
366 /**
367 * Override and disallow this, to prevent people accidentally calling it and actually
368 * getting VclPtr::Create and getting a naked VclPtr<> instance
369 */
370 template<typename... Arg> static ScopedVclPtr< reference_type > Create(Arg &&... ) = delete;
371
372 ~ScopedVclPtr()
373 {
374 VclPtr<reference_type>::disposeAndClear();
12
Calling 'VclPtr::disposeAndClear'
375 assert(VclPtr<reference_type>::get() == nullptr)(static_cast <bool> (VclPtr<reference_type>::get(
) == nullptr) ? void (0) : __assert_fail ("VclPtr<reference_type>::get() == nullptr"
, "/home/maarten/src/libreoffice/core/include/vcl/vclptr.hxx"
, 375, __extension__ __PRETTY_FUNCTION__))
; // make sure there are no lingering references
376 }
377
378private:
379 // Most likely we don't want this default copy-constructor.
380 ScopedVclPtr (const ScopedVclPtr<reference_type> &) = delete;
381 // And certainly we don't want a default assignment operator.
382 ScopedVclPtr<reference_type>& operator = (const ScopedVclPtr<reference_type> &) = delete;
383 // And disallow reset as that doesn't call disposeAndClear on the original reference
384 void reset() = delete;
385 void reset(reference_type *pBody) = delete;
386
387protected:
388 ScopedVclPtr (reference_type * pBody, __sal_NoAcquire)
389 : VclPtr<reference_type>(pBody, SAL_NO_ACQUIRE)
390 {}
391};
392
393/**
394 * A construction helper for ScopedVclPtr. Since VclPtr types are created
395 * with a reference-count of one - to help fit into the existing
396 * code-flow; this helps us to construct them easily.
397 *
398 * For more details on the design please see vcl/README.lifecycle
399 *
400 * @param reference_type must be a subclass of vcl::Window
401 */
402#if defined _MSC_VER
403#pragma warning(push)
404#pragma warning(disable: 4521) // " multiple copy constructors specified"
405#endif
406template <class reference_type>
407class SAL_WARN_UNUSED__attribute__((warn_unused)) ScopedVclPtrInstance final : public ScopedVclPtr<reference_type>
408{
409public:
410 template<typename... Arg> ScopedVclPtrInstance(Arg &&... arg)
411 : ScopedVclPtr<reference_type>( new reference_type(std::forward<Arg>(arg)...), SAL_NO_ACQUIRE )
8
Memory is allocated
412 {
413 }
414
415 /**
416 * Override and disallow this, to prevent people accidentally calling it and actually
417 * getting VclPtr::Create and getting a naked VclPtr<> instance
418 */
419 template<typename... Arg> static ScopedVclPtrInstance< reference_type > Create(Arg &&...) = delete;
420
421private:
422 // Prevent the above perfect forwarding ctor from hijacking (accidental)
423 // attempts at ScopedVclPtrInstance copy construction (where the hijacking
424 // would typically lead to somewhat obscure error messages); both non-const
425 // and const variants are needed here, as the ScopedVclPtr base class has a
426 // const--variant copy ctor, so the implicitly declared copy ctor for
427 // ScopedVclPtrInstance would also be the const variant, so non-const copy
428 // construction attempts would be hijacked by the perfect forwarding ctor;
429 // but if we only declared a non-const variant here, the const variant would
430 // no longer be implicitly declared (as there would already be an explicitly
431 // declared copy ctor), so const copy construction attempts would then be
432 // hijacked by the perfect forwarding ctor:
433 ScopedVclPtrInstance(ScopedVclPtrInstance &) = delete;
434 ScopedVclPtrInstance(ScopedVclPtrInstance const &) = delete;
435};
436#if defined _MSC_VER
437#pragma warning(pop)
438#endif
439
440#endif // INCLUDED_VCL_PTR_HXX
441
442/* vim:set shiftwidth=4 softtabstop=4 expandtab: */

/home/maarten/src/libreoffice/core/include/rtl/ref.hxx

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#ifndef INCLUDED_RTL_REF_HXX
21#define INCLUDED_RTL_REF_HXX
22
23#include "sal/config.h"
24
25#include <cassert>
26#include <cstddef>
27#include <functional>
28#ifdef LIBO_INTERNAL_ONLY1
29#include <type_traits>
30#endif
31
32#include "sal/types.h"
33
34namespace rtl
35{
36
37/** Template reference class for reference type.
38*/
39template <class reference_type>
40class Reference
41{
42 /** The <b>reference_type</b> body pointer.
43 */
44 reference_type * m_pBody;
45
46
47public:
48 /** Constructor...
49 */
50 Reference()
51 : m_pBody (NULL__null)
52 {}
53
54
55 /** Constructor...
56 */
57 Reference (reference_type * pBody, __sal_NoAcquire)
58 : m_pBody (pBody)
59 {
60 }
61
62 /** Constructor...
63 */
64 Reference (reference_type * pBody)
65 : m_pBody (pBody)
66 {
67 if (m_pBody)
68 m_pBody->acquire();
69 }
70
71 /** Copy constructor...
72 */
73 Reference (const Reference<reference_type> & handle)
74 : m_pBody (handle.m_pBody)
75 {
76 if (m_pBody)
77 m_pBody->acquire();
78 }
79
80#ifdef LIBO_INTERNAL_ONLY1
81 /** Move constructor...
82 */
83 Reference (Reference<reference_type> && handle) noexcept
84 : m_pBody (handle.m_pBody)
85 {
86 handle.m_pBody = nullptr;
87 }
88#endif
89
90#if defined LIBO_INTERNAL_ONLY1
91 /** Up-casting conversion constructor: Copies interface reference.
92
93 Does not work for up-casts to ambiguous bases.
94
95 @param rRef another reference
96 */
97 template< class derived_type >
98 inline Reference(
99 const Reference< derived_type > & rRef,
100 std::enable_if_t<std::is_base_of_v<reference_type, derived_type>, int> = 0 )
101 : m_pBody (rRef.get())
102 {
103 if (m_pBody)
104 m_pBody->acquire();
105 }
106#endif
107
108 /** Destructor...
109 */
110 ~Reference() COVERITY_NOEXCEPT_FALSE
111 {
112 if (m_pBody)
113 m_pBody->release();
114 }
115
116 /** Set...
117 Similar to assignment.
118 */
119 Reference<reference_type> &
120 SAL_CALL set (reference_type * pBody)
121 {
122 if (pBody)
123 pBody->acquire();
124 reference_type * const pOld = m_pBody;
125 m_pBody = pBody;
126 if (pOld)
127 pOld->release();
128 return *this;
129 }
130
131 /** Assignment.
132 Unbinds this instance from its body (if bound) and
133 bind it to the body represented by the handle.
134 */
135 Reference<reference_type> &
136 SAL_CALL operator= (const Reference<reference_type> & handle)
137 {
138 return set( handle.m_pBody );
139 }
140
141#ifdef LIBO_INTERNAL_ONLY1
142 /** Assignment.
143 * Unbinds this instance from its body (if bound),
144 * bind it to the body represented by the handle, and
145 * set the body represented by the handle to nullptr.
146 */
147 Reference<reference_type> &
148 operator= (Reference<reference_type> && handle)
149 {
150 // self-movement guts ourself
151 if (m_pBody)
152 m_pBody->release();
153 m_pBody = handle.m_pBody;
154 handle.m_pBody = nullptr;
155 return *this;
156 }
157#endif
158
159 /** Assignment...
160 */
161 Reference<reference_type> &
162 SAL_CALL operator= (reference_type * pBody)
163 {
164 return set( pBody );
165 }
166
167 /** Unbind the body from this handle.
168 Note that for a handle representing a large body,
169 "handle.clear().set(new body());" _might_
170 perform a little bit better than "handle.set(new body());",
171 since in the second case two large objects exist in memory
172 (the old body and the new body).
173 */
174 Reference<reference_type> & SAL_CALL clear()
175 {
176 if (m_pBody
13.1
Field 'm_pBody' is non-null
13.1
Field 'm_pBody' is non-null
13.1
Field 'm_pBody' is non-null
13.1
Field 'm_pBody' is non-null
)
14
Taking true branch
177 {
178 reference_type * const pOld = m_pBody;
179 m_pBody = NULL__null;
180 pOld->release();
15
Calling 'VclReferenceBase::release'
19
Returning; memory was released
181 }
182 return *this;
183 }
184
185
186 /** Get the body. Can be used instead of operator->().
187 I.e. handle->someBodyOp() and handle.get()->someBodyOp()
188 are the same.
189 */
190 reference_type * SAL_CALL get() const
191 {
192 return m_pBody;
22
Use of memory after it is freed
193 }
194
195
196 /** Probably most common used: handle->someBodyOp().
197 */
198 reference_type * SAL_CALL operator->() const
199 {
200 assert(m_pBody != NULL)(static_cast <bool> (m_pBody != __null) ? void (0) : __assert_fail
("m_pBody != NULL", "/home/maarten/src/libreoffice/core/include/rtl/ref.hxx"
, 200, __extension__ __PRETTY_FUNCTION__))
;
201 return m_pBody;
202 }
203
204
205 /** Allows (*handle).someBodyOp().
206 */
207 reference_type & SAL_CALL operator*() const
208 {
209 assert(m_pBody != NULL)(static_cast <bool> (m_pBody != __null) ? void (0) : __assert_fail
("m_pBody != NULL", "/home/maarten/src/libreoffice/core/include/rtl/ref.hxx"
, 209, __extension__ __PRETTY_FUNCTION__))
;
210 return *m_pBody;
211 }
212
213
214 /** Returns True if the handle does point to a valid body.
215 */
216 bool SAL_CALL is() const
217 {
218 return (m_pBody != NULL__null);
219 }
220
221#if defined LIBO_INTERNAL_ONLY1
222 /** Returns True if the handle does point to a valid body.
223 */
224 explicit operator bool() const
225 {
226 return is();
227 }
228#endif
229
230 /** Returns True if this points to pBody.
231 */
232 bool SAL_CALL operator== (const reference_type * pBody) const
233 {
234 return (m_pBody == pBody);
235 }
236
237
238 /** Returns True if handle points to the same body.
239 */
240 bool
241 SAL_CALL operator== (const Reference<reference_type> & handle) const
242 {
243 return (m_pBody == handle.m_pBody);
244 }
245
246
247 /** Needed to place References into STL collection.
248 */
249 bool
250 SAL_CALL operator!= (const Reference<reference_type> & handle) const
251 {
252 return (m_pBody != handle.m_pBody);
253 }
254
255
256 /** Needed to place References into STL collection.
257 */
258 bool
259 SAL_CALL operator< (const Reference<reference_type> & handle) const
260 {
261 return (m_pBody < handle.m_pBody);
262 }
263
264
265 /** Needed to place References into STL collection.
266 */
267 bool
268 SAL_CALL operator> (const Reference<reference_type> & handle) const
269 {
270 return (m_pBody > handle.m_pBody);
271 }
272};
273
274} // namespace rtl
275
276#if defined LIBO_INTERNAL_ONLY1
277namespace std
278{
279
280/// @cond INTERNAL
281/**
282 Make rtl::Reference hashable by default for use in STL containers.
283
284 @since LibreOffice 6.3
285*/
286template<typename T>
287struct hash<::rtl::Reference<T>>
288{
289 std::size_t operator()(::rtl::Reference<T> const & s) const
290 { return std::size_t(s.get()); }
291};
292/// @endcond
293
294}
295
296#endif
297
298#endif /* ! INCLUDED_RTL_REF_HXX */
299
300/* vim:set shiftwidth=4 softtabstop=4 expandtab: */

/home/maarten/src/libreoffice/core/include/vcl/vclreferencebase.hxx

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#ifndef INCLUDED_VCL_Reference_HXX
20#define INCLUDED_VCL_Reference_HXX
21
22#include <vcl/dllapi.h>
23#include <osl/interlck.h>
24
25class VCL_DLLPUBLIC__attribute__ ((visibility("default"))) VclReferenceBase
26{
27 mutable oslInterlockedCount mnRefCnt;
28
29 template<typename T> friend class VclPtr;
30
31public:
32 void acquire() const
33 {
34 osl_atomic_increment(&mnRefCnt)__sync_add_and_fetch((&mnRefCnt), 1);
35 }
36
37 void release() const
38 {
39 if (osl_atomic_decrement(&mnRefCnt)__sync_sub_and_fetch((&mnRefCnt), 1) == 0)
16
Assuming the condition is true
17
Taking true branch
40 delete this;
18
Memory is released
41 }
42#ifdef DBG_UTIL
43#ifndef _WIN32
44 sal_Int32 getRefCount() const { return mnRefCnt; }
45#endif
46#endif
47
48
49private:
50 VclReferenceBase(const VclReferenceBase&) = delete;
51 VclReferenceBase& operator=(const VclReferenceBase&) = delete;
52
53 bool mbDisposed : 1;
54
55protected:
56 VclReferenceBase();
57protected:
58 virtual ~VclReferenceBase();
59
60protected:
61 virtual void dispose();
62
63public:
64 void disposeOnce();
65 bool isDisposed() const { return mbDisposed; }
66
67};
68#endif