Coverage Report

Created: 2026-04-09 11:41

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