Coverage Report

Created: 2025-12-31 10:39

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/libreoffice/svx/source/svdraw/svdhdl.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 <algorithm>
22
#include <cassert>
23
24
#include <svx/svdhdl.hxx>
25
#include <svx/svdpagv.hxx>
26
#include <svx/svdmrkv.hxx>
27
#include <utility>
28
#include <vcl/settings.hxx>
29
#include <vcl/virdev.hxx>
30
#include <vcl/ptrstyle.hxx>
31
32
#include <svx/sxekitm.hxx>
33
#include <svx/strings.hrc>
34
#include <svx/svdmodel.hxx>
35
#include "gradtrns.hxx"
36
#include <svx/xflgrit.hxx>
37
#include <svx/svdundo.hxx>
38
#include <svx/dialmgr.hxx>
39
#include <svx/xflftrit.hxx>
40
41
#include <svx/svdopath.hxx>
42
#include <basegfx/vector/b2dvector.hxx>
43
#include <basegfx/polygon/b2dpolygon.hxx>
44
#include <svx/sdr/overlay/overlaymanager.hxx>
45
#include <svx/sdr/overlay/overlayanimatedbitmapex.hxx>
46
#include <svx/sdr/overlay/overlaybitmapex.hxx>
47
#include <sdr/overlay/overlayline.hxx>
48
#include <sdr/overlay/overlaytriangle.hxx>
49
#include <sdr/overlay/overlayhandle.hxx>
50
#include <sdr/overlay/overlayrectangle.hxx>
51
#include <svx/sdrpagewindow.hxx>
52
#include <svx/sdrpaintwindow.hxx>
53
#include <vcl/svapp.hxx>
54
#include <svx/sdr/overlay/overlaypolypolygon.hxx>
55
#include <tools/lazydelete.hxx>
56
#include <vcl/BitmapTools.hxx>
57
#include <svx/sdr/contact/objectcontact.hxx>
58
#include <svx/sdr/contact/viewcontact.hxx>
59
#include <osl/diagnose.h>
60
61
#include <basegfx/polygon/b2dpolygontools.hxx>
62
#include <svx/sdr/overlay/overlayprimitive2dsequenceobject.hxx>
63
#include <drawinglayer/primitive2d/PolygonHairlinePrimitive2D.hxx>
64
#include <drawinglayer/primitive2d/graphicprimitive2d.hxx>
65
#include <drawinglayer/primitive2d/maskprimitive2d.hxx>
66
#include <drawinglayer/primitive2d/unifiedtransparenceprimitive2d.hxx>
67
#include <svtools/optionsdrawinglayer.hxx>
68
#include <memory>
69
#include <bitmaps.hlst>
70
71
namespace {
72
73
// #i15222#
74
// Due to the resource problems in Win95/98 with bitmap resources I
75
// will change this handle bitmap providing class. Old version was splitting
76
// and preparing all small handle bitmaps in device bitmap format, now this will
77
// be done on the fly. Thus, there is only one big bitmap in memory. With
78
// three source bitmaps, this will be 3 system bitmap resources instead of hundreds.
79
// The price for that needs to be evaluated. Maybe we will need another change here
80
// if this is too expensive.
81
class SdrHdlBitmapSet
82
{
83
    // the bitmap holding all information
84
    Bitmap                      maMarkersBitmap;
85
86
    // the cropped Bitmaps for reusage
87
    ::std::vector< Bitmap >     maRealMarkers;
88
89
    // helpers
90
    Bitmap& impGetOrCreateTargetBitmap(sal_uInt16 nIndex, const tools::Rectangle& rRectangle);
91
92
public:
93
    explicit SdrHdlBitmapSet();
94
95
    const Bitmap& GetBitmap(BitmapMarkerKind eKindOfMarker, sal_uInt16 nInd);
96
};
97
98
}
99
100
0
#define KIND_COUNT          (14)
101
0
#define INDEX_COUNT         (6)
102
0
#define INDIVIDUAL_COUNT    (5)
103
104
SdrHdlBitmapSet::SdrHdlBitmapSet()
105
0
    :   maMarkersBitmap(SIP_SA_MARKERS),
106
        // 15 kinds (BitmapMarkerKind) use index [0..5] + 5 extra
107
0
        maRealMarkers((KIND_COUNT * INDEX_COUNT) + INDIVIDUAL_COUNT)
108
0
{
109
0
}
110
111
Bitmap& SdrHdlBitmapSet::impGetOrCreateTargetBitmap(sal_uInt16 nIndex, const tools::Rectangle& rRectangle)
112
0
{
113
0
    Bitmap& rTargetBitmap = maRealMarkers[nIndex];
114
115
0
    if(rTargetBitmap.IsEmpty())
116
0
    {
117
0
        rTargetBitmap = maMarkersBitmap;
118
0
        rTargetBitmap.Crop(rRectangle);
119
0
    }
120
121
0
    return rTargetBitmap;
122
0
}
123
124
// change getting of bitmap to use the big resource bitmap
125
const Bitmap& SdrHdlBitmapSet::GetBitmap(BitmapMarkerKind eKindOfMarker, sal_uInt16 nInd)
126
0
{
127
    // fill in size and source position in maMarkersBitmap
128
0
    const sal_uInt16 nYPos(nInd * 11);
129
130
0
    switch(eKindOfMarker)
131
0
    {
132
0
        default:
133
0
        {
134
0
            OSL_FAIL( "Unknown kind of marker." );
135
0
            [[fallthrough]]; // return Rect_9x9 as default
136
0
        }
137
0
        case BitmapMarkerKind::Rect_9x9:
138
0
        {
139
0
            return impGetOrCreateTargetBitmap((1 * INDEX_COUNT) + nInd, tools::Rectangle(Point(7, nYPos), Size(9, 9)));
140
0
        }
141
142
0
        case BitmapMarkerKind::Rect_7x7:
143
0
        {
144
0
            return impGetOrCreateTargetBitmap((0 * INDEX_COUNT) + nInd, tools::Rectangle(Point(0, nYPos), Size(7, 7)));
145
0
        }
146
147
0
        case BitmapMarkerKind::Rect_11x11:
148
0
        {
149
0
            return impGetOrCreateTargetBitmap((2 * INDEX_COUNT) + nInd, tools::Rectangle(Point(16, nYPos), Size(11, 11)));
150
0
        }
151
152
0
        case BitmapMarkerKind::Rect_13x13:
153
0
        {
154
0
            const sal_uInt16 nIndex((3 * INDEX_COUNT) + nInd);
155
156
0
            switch(nInd)
157
0
            {
158
0
                case 0:
159
0
                {
160
0
                    return impGetOrCreateTargetBitmap(nIndex, tools::Rectangle(Point(72, 66), Size(13, 13)));
161
0
                }
162
0
                case 1:
163
0
                {
164
0
                    return impGetOrCreateTargetBitmap(nIndex, tools::Rectangle(Point(85, 66), Size(13, 13)));
165
0
                }
166
0
                case 2:
167
0
                {
168
0
                    return impGetOrCreateTargetBitmap(nIndex, tools::Rectangle(Point(72, 79), Size(13, 13)));
169
0
                }
170
0
                case 3:
171
0
                {
172
0
                    return impGetOrCreateTargetBitmap(nIndex, tools::Rectangle(Point(85, 79), Size(13, 13)));
173
0
                }
174
0
                case 4:
175
0
                {
176
0
                    return impGetOrCreateTargetBitmap(nIndex, tools::Rectangle(Point(98, 79), Size(13, 13)));
177
0
                }
178
0
                default: // case 5:
179
0
                {
180
0
                    return impGetOrCreateTargetBitmap(nIndex, tools::Rectangle(Point(98, 66), Size(13, 13)));
181
0
                }
182
0
            }
183
0
        }
184
185
0
        case BitmapMarkerKind::Circ_7x7:
186
0
        case BitmapMarkerKind::Customshape_7x7:
187
0
        {
188
0
            return impGetOrCreateTargetBitmap((4 * INDEX_COUNT) + nInd, tools::Rectangle(Point(27, nYPos), Size(7, 7)));
189
0
        }
190
191
0
        case BitmapMarkerKind::Circ_9x9:
192
0
        case BitmapMarkerKind::Customshape_9x9:
193
0
        {
194
0
            return impGetOrCreateTargetBitmap((5 * INDEX_COUNT) + nInd, tools::Rectangle(Point(34, nYPos), Size(9, 9)));
195
0
        }
196
197
0
        case BitmapMarkerKind::Circ_11x11:
198
0
        case BitmapMarkerKind::Customshape_11x11:
199
0
        {
200
0
            return impGetOrCreateTargetBitmap((6 * INDEX_COUNT) + nInd, tools::Rectangle(Point(43, nYPos), Size(11, 11)));
201
0
        }
202
203
0
        case BitmapMarkerKind::Elli_7x9:
204
0
        {
205
0
            return impGetOrCreateTargetBitmap((7 * INDEX_COUNT) + nInd, tools::Rectangle(Point(54, nYPos), Size(7, 9)));
206
0
        }
207
208
0
        case BitmapMarkerKind::Elli_9x11:
209
0
        {
210
0
            return impGetOrCreateTargetBitmap((8 * INDEX_COUNT) + nInd, tools::Rectangle(Point(61, nYPos), Size(9, 11)));
211
0
        }
212
213
0
        case BitmapMarkerKind::Elli_9x7:
214
0
        {
215
0
            return impGetOrCreateTargetBitmap((9 * INDEX_COUNT) + nInd, tools::Rectangle(Point(70, nYPos), Size(9, 7)));
216
0
        }
217
218
0
        case BitmapMarkerKind::Elli_11x9:
219
0
        {
220
0
            return impGetOrCreateTargetBitmap((10 * INDEX_COUNT) + nInd, tools::Rectangle(Point(79, nYPos), Size(11, 9)));
221
0
        }
222
223
0
        case BitmapMarkerKind::RectPlus_7x7:
224
0
        {
225
0
            return impGetOrCreateTargetBitmap((11 * INDEX_COUNT) + nInd, tools::Rectangle(Point(90, nYPos), Size(7, 7)));
226
0
        }
227
228
0
        case BitmapMarkerKind::RectPlus_9x9:
229
0
        {
230
0
            return impGetOrCreateTargetBitmap((12 * INDEX_COUNT) + nInd, tools::Rectangle(Point(97, nYPos), Size(9, 9)));
231
0
        }
232
233
0
        case BitmapMarkerKind::RectPlus_11x11:
234
0
        {
235
0
            return impGetOrCreateTargetBitmap((13 * INDEX_COUNT) + nInd, tools::Rectangle(Point(106, nYPos), Size(11, 11)));
236
0
        }
237
238
0
        case BitmapMarkerKind::Crosshair:
239
0
        {
240
0
            return impGetOrCreateTargetBitmap((KIND_COUNT * INDEX_COUNT) + 0, tools::Rectangle(Point(0, 68), Size(15, 15)));
241
0
        }
242
243
0
        case BitmapMarkerKind::Glue:
244
0
        {
245
0
            return impGetOrCreateTargetBitmap((KIND_COUNT * INDEX_COUNT) + 1, tools::Rectangle(Point(15, 76), Size(9, 9)));
246
0
        }
247
248
0
        case BitmapMarkerKind::Glue_Deselected:
249
0
        {
250
0
            return impGetOrCreateTargetBitmap((KIND_COUNT * INDEX_COUNT) + 2, tools::Rectangle(Point(15, 67), Size(9, 9)));
251
0
        }
252
253
0
        case BitmapMarkerKind::Anchor: // AnchorTR for SW
254
0
        case BitmapMarkerKind::AnchorTR:
255
0
        {
256
0
            return impGetOrCreateTargetBitmap((KIND_COUNT * INDEX_COUNT) + 3, tools::Rectangle(Point(24, 67), Size(24, 24)));
257
0
        }
258
259
        // add AnchorPressed to be able to animate anchor control
260
0
        case BitmapMarkerKind::AnchorPressed:
261
0
        case BitmapMarkerKind::AnchorPressedTR:
262
0
        {
263
0
            return impGetOrCreateTargetBitmap((KIND_COUNT * INDEX_COUNT) + 4, tools::Rectangle(Point(48, 67), Size(24, 24)));
264
0
        }
265
0
    }
266
0
}
267
268
269
SdrHdl::SdrHdl():
270
0
    m_pObj(nullptr),
271
0
    m_pPV(nullptr),
272
0
    m_pHdlList(nullptr),
273
0
    m_eKind(SdrHdlKind::Move),
274
0
    m_nRotationAngle(0),
275
0
    m_nObjHdlNum(0),
276
0
    m_nPolyNum(0),
277
0
    m_nPPntNum(0),
278
0
    m_nSourceHdlNum(0),
279
0
    m_bSelect(false),
280
0
    m_b1PixMore(false),
281
0
    m_bPlusHdl(false),
282
0
    mbMoveOutside(false),
283
0
    mbMouseOver(false)
284
0
{
285
0
}
286
287
SdrHdl::SdrHdl(const Point& rPnt, SdrHdlKind eNewKind):
288
0
    m_pObj(nullptr),
289
0
    m_pPV(nullptr),
290
0
    m_pHdlList(nullptr),
291
0
    m_aPos(rPnt),
292
0
    m_eKind(eNewKind),
293
0
    m_nRotationAngle(0),
294
0
    m_nObjHdlNum(0),
295
0
    m_nPolyNum(0),
296
0
    m_nPPntNum(0),
297
0
    m_nSourceHdlNum(0),
298
0
    m_bSelect(false),
299
0
    m_b1PixMore(false),
300
0
    m_bPlusHdl(false),
301
0
    mbMoveOutside(false),
302
0
    mbMouseOver(false)
303
0
{
304
0
}
305
306
SdrHdl::~SdrHdl()
307
0
{
308
0
    GetRidOfIAObject();
309
0
}
310
311
void SdrHdl::Set1PixMore(bool bJa)
312
0
{
313
0
    if(m_b1PixMore != bJa)
314
0
    {
315
0
        m_b1PixMore = bJa;
316
317
        // create new display
318
0
        Touch();
319
0
    }
320
0
}
321
322
void SdrHdl::SetMoveOutside( bool bMoveOutside )
323
0
{
324
0
    if(mbMoveOutside != bMoveOutside)
325
0
    {
326
0
        mbMoveOutside = bMoveOutside;
327
328
        // create new display
329
0
        Touch();
330
0
    }
331
0
}
332
333
void SdrHdl::SetRotationAngle(Degree100 n)
334
0
{
335
0
    if(m_nRotationAngle != n)
336
0
    {
337
0
        m_nRotationAngle = n;
338
339
        // create new display
340
0
        Touch();
341
0
    }
342
0
}
343
344
void SdrHdl::SetPos(const Point& rPnt)
345
0
{
346
0
    if(m_aPos != rPnt)
347
0
    {
348
        // remember new position
349
0
        m_aPos = rPnt;
350
351
        // create new display
352
0
        Touch();
353
0
    }
354
0
}
355
356
void SdrHdl::SetSelected(bool bJa)
357
0
{
358
0
    if(m_bSelect != bJa)
359
0
    {
360
        // remember new value
361
0
        m_bSelect = bJa;
362
363
        // create new display
364
0
        Touch();
365
0
    }
366
0
}
367
368
void SdrHdl::SetHdlList(SdrHdlList* pList)
369
0
{
370
0
    if(m_pHdlList != pList)
371
0
    {
372
        // remember list
373
0
        m_pHdlList = pList;
374
375
        // now it's possible to create graphic representation
376
0
        Touch();
377
0
    }
378
0
}
379
380
void SdrHdl::SetObj(SdrObject* pNewObj)
381
0
{
382
0
    if(m_pObj != pNewObj)
383
0
    {
384
        // remember new object
385
0
        m_pObj = pNewObj;
386
387
        // graphic representation may have changed
388
0
        Touch();
389
0
    }
390
0
}
391
392
void SdrHdl::Touch()
393
0
{
394
    // force update of graphic representation
395
0
    CreateB2dIAObject();
396
0
}
397
398
void SdrHdl::GetRidOfIAObject()
399
0
{
400
401
    // OVERLAYMANAGER
402
0
    maOverlayGroup.clear();
403
0
}
404
405
void SdrHdl::CreateB2dIAObject()
406
0
{
407
    // first throw away old one
408
0
    GetRidOfIAObject();
409
410
0
    if(!m_pHdlList || !m_pHdlList->GetView() || m_pHdlList->GetView()->areMarkHandlesHidden())
411
0
        return;
412
413
0
    BitmapColorIndex eColIndex = BitmapColorIndex::LightGreen;
414
0
    BitmapMarkerKind eKindOfMarker = BitmapMarkerKind::Rect_7x7;
415
416
0
    bool bRot = m_pHdlList->IsRotateShear();
417
0
    if(m_pObj)
418
0
        eColIndex = m_bSelect ? BitmapColorIndex::Cyan : BitmapColorIndex::LightCyan;
419
0
    if(bRot)
420
0
    {
421
        // red rotation handles
422
0
        if(m_pObj && m_bSelect)
423
0
            eColIndex = BitmapColorIndex::Red;
424
0
        else
425
0
            eColIndex = BitmapColorIndex::LightRed;
426
0
    }
427
428
0
    switch(m_eKind)
429
0
    {
430
0
        case SdrHdlKind::Move:
431
0
        {
432
0
            eKindOfMarker = m_b1PixMore ? BitmapMarkerKind::Rect_9x9 : BitmapMarkerKind::Rect_7x7;
433
0
            break;
434
0
        }
435
0
        case SdrHdlKind::UpperLeft:
436
0
        case SdrHdlKind::UpperRight:
437
0
        case SdrHdlKind::LowerLeft:
438
0
        case SdrHdlKind::LowerRight:
439
0
        {
440
            // corner handles
441
0
            if(bRot)
442
0
            {
443
0
                eKindOfMarker = BitmapMarkerKind::Circ_7x7;
444
0
            }
445
0
            else
446
0
            {
447
0
                eKindOfMarker = BitmapMarkerKind::Rect_7x7;
448
0
            }
449
0
            break;
450
0
        }
451
0
        case SdrHdlKind::Upper:
452
0
        case SdrHdlKind::Lower:
453
0
        {
454
            // Upper/Lower handles
455
0
            if(bRot)
456
0
            {
457
0
                eKindOfMarker = BitmapMarkerKind::Elli_9x7;
458
0
            }
459
0
            else
460
0
            {
461
0
                eKindOfMarker = BitmapMarkerKind::Rect_7x7;
462
0
            }
463
0
            break;
464
0
        }
465
0
        case SdrHdlKind::Left:
466
0
        case SdrHdlKind::Right:
467
0
        {
468
            // Left/Right handles
469
0
            if(bRot)
470
0
            {
471
0
                eKindOfMarker = BitmapMarkerKind::Elli_7x9;
472
0
            }
473
0
            else
474
0
            {
475
0
                eKindOfMarker = BitmapMarkerKind::Rect_7x7;
476
0
            }
477
0
            break;
478
0
        }
479
0
        case SdrHdlKind::Poly:
480
0
        {
481
0
            if(bRot)
482
0
            {
483
0
                eKindOfMarker = m_b1PixMore ? BitmapMarkerKind::Circ_9x9 : BitmapMarkerKind::Circ_7x7;
484
0
            }
485
0
            else
486
0
            {
487
0
                eKindOfMarker = m_b1PixMore ? BitmapMarkerKind::Rect_9x9 : BitmapMarkerKind::Rect_7x7;
488
0
            }
489
0
            break;
490
0
        }
491
0
        case SdrHdlKind::BezierWeight: // weight at poly
492
0
        {
493
0
            eKindOfMarker = BitmapMarkerKind::Circ_7x7;
494
0
            break;
495
0
        }
496
0
        case SdrHdlKind::Circle:
497
0
        {
498
0
            eKindOfMarker = BitmapMarkerKind::Rect_11x11;
499
0
            break;
500
0
        }
501
0
        case SdrHdlKind::Ref1:
502
0
        case SdrHdlKind::Ref2:
503
0
        {
504
0
            eKindOfMarker = BitmapMarkerKind::Crosshair;
505
0
            break;
506
0
        }
507
0
        case SdrHdlKind::Glue:
508
0
        {
509
0
            eKindOfMarker = BitmapMarkerKind::Glue;
510
0
            break;
511
0
        }
512
0
        case SdrHdlKind::Anchor:
513
0
        {
514
0
            eKindOfMarker = BitmapMarkerKind::Anchor;
515
0
            break;
516
0
        }
517
0
        case SdrHdlKind::User:
518
0
        {
519
0
            break;
520
0
        }
521
        // top right anchor for SW
522
0
        case SdrHdlKind::Anchor_TR:
523
0
        {
524
0
            eKindOfMarker = BitmapMarkerKind::AnchorTR;
525
0
            break;
526
0
        }
527
528
        // for SJ and the CustomShapeHandles:
529
0
        case SdrHdlKind::CustomShape1:
530
0
        {
531
0
            eKindOfMarker = m_b1PixMore ? BitmapMarkerKind::Customshape_9x9 : BitmapMarkerKind::Customshape_7x7;
532
0
            eColIndex = BitmapColorIndex::Yellow;
533
0
            break;
534
0
        }
535
0
        default:
536
0
            break;
537
0
    }
538
539
0
    SdrMarkView* pView = m_pHdlList->GetView();
540
0
    SdrPageView* pPageView = pView->GetSdrPageView();
541
542
0
    if(!pPageView)
543
0
        return;
544
545
0
    for(sal_uInt32 b(0); b < pPageView->PageWindowCount(); b++)
546
0
    {
547
        // const SdrPageViewWinRec& rPageViewWinRec = rPageViewWinList[b];
548
0
        const SdrPageWindow& rPageWindow = *pPageView->GetPageWindow(b);
549
550
0
        if(rPageWindow.GetPaintWindow().OutputToWindow())
551
0
        {
552
0
            Point aMoveOutsideOffset(0, 0);
553
0
            OutputDevice& rOutDev = rPageWindow.GetPaintWindow().GetOutputDevice();
554
555
            // add offset if necessary
556
0
            if(m_pHdlList->IsMoveOutside() || mbMoveOutside)
557
0
            {
558
0
                Size aOffset = rOutDev.PixelToLogic(Size(4, 4));
559
560
0
                if(m_eKind == SdrHdlKind::UpperLeft || m_eKind == SdrHdlKind::Upper || m_eKind == SdrHdlKind::UpperRight)
561
0
                    aMoveOutsideOffset.AdjustY( -(aOffset.Width()) );
562
0
                if(m_eKind == SdrHdlKind::LowerLeft || m_eKind == SdrHdlKind::Lower || m_eKind == SdrHdlKind::LowerRight)
563
0
                    aMoveOutsideOffset.AdjustY(aOffset.Height() );
564
0
                if(m_eKind == SdrHdlKind::UpperLeft || m_eKind == SdrHdlKind::Left  || m_eKind == SdrHdlKind::LowerLeft)
565
0
                    aMoveOutsideOffset.AdjustX( -(aOffset.Width()) );
566
0
                if(m_eKind == SdrHdlKind::UpperRight || m_eKind == SdrHdlKind::Right || m_eKind == SdrHdlKind::LowerRight)
567
0
                    aMoveOutsideOffset.AdjustX(aOffset.Height() );
568
0
            }
569
570
0
            const rtl::Reference< sdr::overlay::OverlayManager >& xManager = rPageWindow.GetOverlayManager();
571
0
            if (xManager.is())
572
0
            {
573
0
                basegfx::B2DPoint aPosition(m_aPos.X(), m_aPos.Y());
574
0
                std::unique_ptr<sdr::overlay::OverlayObject> pNewOverlayObject;
575
0
                if (getenv ("SVX_DRAW_HANDLES") && (eKindOfMarker == BitmapMarkerKind::Rect_7x7 || eKindOfMarker == BitmapMarkerKind::Rect_9x9 || eKindOfMarker == BitmapMarkerKind::Rect_11x11))
576
0
                {
577
0
                    double fSize = 7.0;
578
0
                    switch (eKindOfMarker)
579
0
                    {
580
0
                        case BitmapMarkerKind::Rect_9x9:
581
0
                            fSize = 9.0;
582
0
                            break;
583
0
                        case BitmapMarkerKind::Rect_11x11:
584
0
                            fSize = 11.0;
585
0
                            break;
586
0
                        default:
587
0
                            break;
588
0
                    }
589
0
                    float fScalingFactor = rOutDev.GetDPIScaleFactor();
590
0
                    basegfx::B2DSize aB2DSize(fSize * fScalingFactor, fSize * fScalingFactor);
591
592
0
                    Color aHandleFillColor(COL_LIGHTGREEN);
593
0
                    switch (eColIndex)
594
0
                    {
595
0
                        case BitmapColorIndex::Cyan:
596
0
                            aHandleFillColor = COL_CYAN;
597
0
                            break;
598
0
                        case BitmapColorIndex::LightCyan:
599
0
                            aHandleFillColor = COL_LIGHTCYAN;
600
0
                            break;
601
0
                        case BitmapColorIndex::Red:
602
0
                            aHandleFillColor = COL_RED;
603
0
                            break;
604
0
                        case BitmapColorIndex::LightRed:
605
0
                            aHandleFillColor = COL_LIGHTRED;
606
0
                            break;
607
0
                        case BitmapColorIndex::Yellow:
608
0
                            aHandleFillColor = COL_YELLOW;
609
0
                            break;
610
0
                        default:
611
0
                            break;
612
0
                    }
613
0
                    pNewOverlayObject.reset(new sdr::overlay::OverlayHandle(aPosition, aB2DSize, /*HandleStrokeColor*/COL_BLACK, aHandleFillColor));
614
0
                }
615
0
                else
616
0
                {
617
0
                    pNewOverlayObject = CreateOverlayObject(
618
0
                                            aPosition, eColIndex, eKindOfMarker,
619
0
                                            aMoveOutsideOffset);
620
0
                }
621
622
                // OVERLAYMANAGER
623
0
                insertNewlyCreatedOverlayObjectForSdrHdl(
624
0
                    std::move(pNewOverlayObject),
625
0
                    rPageWindow.GetObjectContact(),
626
0
                    *xManager);
627
0
            }
628
0
        }
629
0
    }
630
0
}
631
632
BitmapMarkerKind SdrHdl::GetNextBigger(BitmapMarkerKind eKnd)
633
0
{
634
0
    BitmapMarkerKind eRetval(eKnd);
635
636
0
    switch(eKnd)
637
0
    {
638
0
        case BitmapMarkerKind::Rect_7x7:          eRetval = BitmapMarkerKind::Rect_9x9;         break;
639
0
        case BitmapMarkerKind::Rect_9x9:          eRetval = BitmapMarkerKind::Rect_11x11;       break;
640
0
        case BitmapMarkerKind::Rect_11x11:        eRetval = BitmapMarkerKind::Rect_13x13;       break;
641
642
0
        case BitmapMarkerKind::Circ_7x7:          eRetval = BitmapMarkerKind::Circ_9x9;         break;
643
0
        case BitmapMarkerKind::Circ_9x9:          eRetval = BitmapMarkerKind::Circ_11x11;       break;
644
645
0
        case BitmapMarkerKind::Customshape_7x7:       eRetval = BitmapMarkerKind::Customshape_9x9;      break;
646
0
        case BitmapMarkerKind::Customshape_9x9:       eRetval = BitmapMarkerKind::Customshape_11x11;    break;
647
        //case BitmapMarkerKind::Customshape_11x11:   eRetval = ; break;
648
649
0
        case BitmapMarkerKind::Elli_7x9:          eRetval = BitmapMarkerKind::Elli_9x11;        break;
650
651
0
        case BitmapMarkerKind::Elli_9x7:          eRetval = BitmapMarkerKind::Elli_11x9;        break;
652
653
0
        case BitmapMarkerKind::RectPlus_7x7:      eRetval = BitmapMarkerKind::RectPlus_9x9;     break;
654
0
        case BitmapMarkerKind::RectPlus_9x9:      eRetval = BitmapMarkerKind::RectPlus_11x11;   break;
655
656
        // let anchor blink with its pressed state
657
0
        case BitmapMarkerKind::Anchor:            eRetval = BitmapMarkerKind::AnchorPressed;    break;
658
659
        // same for AnchorTR
660
0
        case BitmapMarkerKind::AnchorTR:          eRetval = BitmapMarkerKind::AnchorPressedTR;  break;
661
0
        default:
662
0
            break;
663
0
    }
664
665
0
    return eRetval;
666
0
}
667
668
namespace
669
{
670
671
OUString appendMarkerName(BitmapMarkerKind eKindOfMarker)
672
0
{
673
0
    switch(eKindOfMarker)
674
0
    {
675
0
        case BitmapMarkerKind::Rect_7x7:
676
0
            return u"rect7"_ustr;
677
0
        case BitmapMarkerKind::Rect_9x9:
678
0
            return u"rect9"_ustr;
679
0
        case BitmapMarkerKind::Rect_11x11:
680
0
            return u"rect11"_ustr;
681
0
        case BitmapMarkerKind::Rect_13x13:
682
0
            return u"rect13"_ustr;
683
0
        case BitmapMarkerKind::Circ_7x7:
684
0
        case BitmapMarkerKind::Customshape_7x7:
685
0
            return u"circ7"_ustr;
686
0
        case BitmapMarkerKind::Circ_9x9:
687
0
        case BitmapMarkerKind::Customshape_9x9:
688
0
            return u"circ9"_ustr;
689
0
        case BitmapMarkerKind::Circ_11x11:
690
0
        case BitmapMarkerKind::Customshape_11x11:
691
0
            return u"circ11"_ustr;
692
0
        case BitmapMarkerKind::Elli_7x9:
693
0
            return u"elli7x9"_ustr;
694
0
        case BitmapMarkerKind::Elli_9x11:
695
0
            return u"elli9x11"_ustr;
696
0
        case BitmapMarkerKind::Elli_9x7:
697
0
            return u"elli9x7"_ustr;
698
0
        case BitmapMarkerKind::Elli_11x9:
699
0
            return u"elli11x9"_ustr;
700
0
        case BitmapMarkerKind::RectPlus_7x7:
701
0
            return u"rectplus7"_ustr;
702
0
        case BitmapMarkerKind::RectPlus_9x9:
703
0
            return u"rectplus9"_ustr;
704
0
        case BitmapMarkerKind::RectPlus_11x11:
705
0
            return u"rectplus11"_ustr;
706
0
        case BitmapMarkerKind::Crosshair:
707
0
            return u"cross"_ustr;
708
0
        case BitmapMarkerKind::Anchor:
709
0
        case BitmapMarkerKind::AnchorTR:
710
0
            return u"anchor"_ustr;
711
0
        case BitmapMarkerKind::AnchorPressed:
712
0
        case BitmapMarkerKind::AnchorPressedTR:
713
0
            return u"anchor-pressed"_ustr;
714
0
        case BitmapMarkerKind::Glue:
715
0
            return u"glue-selected"_ustr;
716
0
        case BitmapMarkerKind::Glue_Deselected:
717
0
            return u"glue-unselected"_ustr;
718
0
        default:
719
0
            break;
720
0
    }
721
0
    return OUString();
722
0
}
723
724
OUString appendMarkerColor(BitmapColorIndex eIndex)
725
0
{
726
0
    switch(eIndex)
727
0
    {
728
0
        case BitmapColorIndex::LightGreen:
729
0
            return u"1"_ustr;
730
0
        case BitmapColorIndex::Cyan:
731
0
            return u"2"_ustr;
732
0
        case BitmapColorIndex::LightCyan:
733
0
            return u"3"_ustr;
734
0
        case BitmapColorIndex::Red:
735
0
            return u"4"_ustr;
736
0
        case BitmapColorIndex::LightRed:
737
0
            return u"5"_ustr;
738
0
        case BitmapColorIndex::Yellow:
739
0
            return u"6"_ustr;
740
0
        default:
741
0
            break;
742
0
    }
743
0
    return OUString();
744
0
}
745
746
Bitmap ImpGetBitmap(BitmapMarkerKind eKindOfMarker, BitmapColorIndex eIndex)
747
0
{
748
    // use this code path only when we use HiDPI (for now)
749
0
    if (Application::GetDefaultDevice()->GetDPIScalePercentage() > 100)
750
0
    {
751
0
        OUString sMarkerName = appendMarkerName(eKindOfMarker);
752
0
        if (!sMarkerName.isEmpty())
753
0
        {
754
0
            OUString sMarkerPrefix(u"svx/res/marker-"_ustr);
755
0
            Bitmap aBitmap;
756
757
0
            if (eKindOfMarker == BitmapMarkerKind::Crosshair
758
0
             || eKindOfMarker == BitmapMarkerKind::Anchor
759
0
             || eKindOfMarker == BitmapMarkerKind::AnchorTR
760
0
             || eKindOfMarker == BitmapMarkerKind::AnchorPressed
761
0
             || eKindOfMarker == BitmapMarkerKind::AnchorPressedTR
762
0
             || eKindOfMarker == BitmapMarkerKind::Glue
763
0
             || eKindOfMarker == BitmapMarkerKind::Glue_Deselected)
764
0
            {
765
0
                aBitmap = vcl::bitmap::loadFromName(sMarkerPrefix + sMarkerName + ".png");
766
0
            }
767
0
            else
768
0
            {
769
0
                aBitmap = vcl::bitmap::loadFromName(sMarkerPrefix + sMarkerName + "-" + appendMarkerColor(eIndex) + ".png");
770
0
            }
771
772
0
            if (!aBitmap.IsEmpty())
773
0
                return aBitmap;
774
0
        }
775
0
    }
776
777
    // if we can't load the marker...
778
779
0
    static tools::DeleteOnDeinit< SdrHdlBitmapSet > aModernSet {};
780
0
    return aModernSet.get()->GetBitmap(eKindOfMarker, sal_uInt16(eIndex));
781
0
}
782
783
} // end anonymous namespace
784
785
std::unique_ptr<sdr::overlay::OverlayObject> SdrHdl::CreateOverlayObject(
786
    const basegfx::B2DPoint& rPos,
787
    BitmapColorIndex eColIndex, BitmapMarkerKind eKindOfMarker, Point aMoveOutsideOffset)
788
0
{
789
0
    std::unique_ptr<sdr::overlay::OverlayObject> pRetval;
790
791
    // support bigger sizes
792
0
    bool bForceBiggerSize(false);
793
794
0
    if (m_pHdlList && m_pHdlList->GetHdlSize() > 3)
795
0
    {
796
0
        switch(eKindOfMarker)
797
0
        {
798
0
            case BitmapMarkerKind::Anchor:
799
0
            case BitmapMarkerKind::AnchorPressed:
800
0
            case BitmapMarkerKind::AnchorTR:
801
0
            case BitmapMarkerKind::AnchorPressedTR:
802
0
            {
803
                // #i121463# For anchor, do not simply make bigger because of HdlSize,
804
                // do it dependent of IsSelected() which Writer can set in drag mode
805
0
                if(IsSelected())
806
0
                {
807
0
                    bForceBiggerSize = true;
808
0
                }
809
0
                break;
810
0
            }
811
0
            default:
812
0
            {
813
0
                bForceBiggerSize = true;
814
0
                break;
815
0
            }
816
0
        }
817
0
    }
818
819
0
    if(bForceBiggerSize)
820
0
    {
821
0
        eKindOfMarker = GetNextBigger(eKindOfMarker);
822
0
    }
823
824
    // This handle has the focus, visualize it
825
0
    if(IsFocusHdl() && m_pHdlList && m_pHdlList->GetFocusHdl() == this)
826
0
    {
827
        // create animated handle
828
0
        BitmapMarkerKind eNextBigger = GetNextBigger(eKindOfMarker);
829
830
0
        if(eNextBigger == eKindOfMarker)
831
0
        {
832
            // this may happen for the not supported getting-bigger types.
833
            // Choose an alternative here
834
0
            switch(eKindOfMarker)
835
0
            {
836
0
                case BitmapMarkerKind::Rect_13x13:        eNextBigger = BitmapMarkerKind::Rect_11x11;   break;
837
0
                case BitmapMarkerKind::Circ_11x11:        eNextBigger = BitmapMarkerKind::Elli_11x9;    break;
838
0
                case BitmapMarkerKind::Elli_9x11:         eNextBigger = BitmapMarkerKind::Elli_11x9;    break;
839
0
                case BitmapMarkerKind::Elli_11x9:         eNextBigger = BitmapMarkerKind::Elli_9x11;    break;
840
0
                case BitmapMarkerKind::RectPlus_11x11:    eNextBigger = BitmapMarkerKind::Rect_13x13;   break;
841
0
                case BitmapMarkerKind::Glue:
842
0
                    eNextBigger = BitmapMarkerKind::Crosshair;
843
0
                    break;
844
0
                case BitmapMarkerKind::Crosshair:
845
0
                case BitmapMarkerKind::Glue_Deselected:
846
0
                    eNextBigger = BitmapMarkerKind::Glue;
847
0
                    break;
848
0
                default:
849
0
                    break;
850
0
            }
851
0
        }
852
853
        // create animated handle
854
0
        Bitmap aBmp1 = ImpGetBitmap(eKindOfMarker, eColIndex);
855
0
        Bitmap aBmp2 = ImpGetBitmap(eNextBigger,   eColIndex);
856
857
        // #i53216# Use system cursor blink time. Use the unsigned value.
858
0
        const StyleSettings& rStyleSettings = Application::GetSettings().GetStyleSettings();
859
0
        const sal_uInt64 nBlinkTime(rStyleSettings.GetCursorBlinkTime());
860
861
0
        if(eKindOfMarker == BitmapMarkerKind::Anchor || eKindOfMarker == BitmapMarkerKind::AnchorPressed)
862
0
        {
863
            // when anchor is used take upper left as reference point inside the handle
864
0
            pRetval.reset(new sdr::overlay::OverlayAnimatedBitmapEx(rPos, aBmp1, aBmp2, nBlinkTime));
865
0
        }
866
0
        else if(eKindOfMarker == BitmapMarkerKind::AnchorTR || eKindOfMarker == BitmapMarkerKind::AnchorPressedTR)
867
0
        {
868
            // AnchorTR for SW, take top right as (0,0)
869
0
            pRetval.reset(new sdr::overlay::OverlayAnimatedBitmapEx(rPos, aBmp1, aBmp2, nBlinkTime,
870
0
                static_cast<sal_uInt16>(aBmp1.GetSizePixel().Width() - 1), 0,
871
0
                static_cast<sal_uInt16>(aBmp2.GetSizePixel().Width() - 1), 0));
872
0
        }
873
0
        else
874
0
        {
875
            // create centered handle as default
876
0
            pRetval.reset(new sdr::overlay::OverlayAnimatedBitmapEx(rPos, aBmp1, aBmp2, nBlinkTime,
877
0
                static_cast<sal_uInt16>(aBmp1.GetSizePixel().Width() - 1) >> 1,
878
0
                static_cast<sal_uInt16>(aBmp1.GetSizePixel().Height() - 1) >> 1,
879
0
                static_cast<sal_uInt16>(aBmp2.GetSizePixel().Width() - 1) >> 1,
880
0
                static_cast<sal_uInt16>(aBmp2.GetSizePixel().Height() - 1) >> 1));
881
0
        }
882
0
    }
883
0
    else
884
0
    {
885
        // create normal handle: use ImpGetBitmapEx(...) now
886
0
        Bitmap aBmp(ImpGetBitmap(eKindOfMarker, eColIndex));
887
888
        // When the image with handles is not found, the bitmap returned is
889
        // empty. This is a problem when we use LibreOffice as a library
890
        // (through LOKit - for example on Android) even when we don't show
891
        // the handles, because the hit test would always return false.
892
        //
893
        // This HACK replaces the empty bitmap with a black 13x13 bitmap handle
894
        // so that the hit test works for this case.
895
0
        if (aBmp.IsEmpty())
896
0
        {
897
0
            aBmp = Bitmap(Size(13, 13), vcl::PixelFormat::N24_BPP);
898
0
            aBmp.Erase(COL_BLACK);
899
0
        }
900
901
0
        if(eKindOfMarker == BitmapMarkerKind::Anchor || eKindOfMarker == BitmapMarkerKind::AnchorPressed)
902
0
        {
903
            // upper left as reference point inside the handle for AnchorPressed, too
904
0
            pRetval.reset(new sdr::overlay::OverlayBitmapEx(rPos, aBmp));
905
0
        }
906
0
        else if(eKindOfMarker == BitmapMarkerKind::AnchorTR || eKindOfMarker == BitmapMarkerKind::AnchorPressedTR)
907
0
        {
908
            // AnchorTR for SW, take top right as (0,0)
909
0
            pRetval.reset(new sdr::overlay::OverlayBitmapEx(rPos, aBmp,
910
0
                static_cast<sal_uInt16>(aBmp.GetSizePixel().Width() - 1), 0));
911
0
        }
912
0
        else
913
0
        {
914
0
            sal_uInt16 nCenX(static_cast<sal_uInt16>(aBmp.GetSizePixel().Width() - 1) >> 1);
915
0
            sal_uInt16 nCenY(static_cast<sal_uInt16>(aBmp.GetSizePixel().Height() - 1) >> 1);
916
917
0
            if(aMoveOutsideOffset.X() > 0)
918
0
            {
919
0
                nCenX = 0;
920
0
            }
921
0
            else if(aMoveOutsideOffset.X() < 0)
922
0
            {
923
0
                nCenX = static_cast<sal_uInt16>(aBmp.GetSizePixel().Width() - 1);
924
0
            }
925
926
0
            if(aMoveOutsideOffset.Y() > 0)
927
0
            {
928
0
                nCenY = 0;
929
0
            }
930
0
            else if(aMoveOutsideOffset.Y() < 0)
931
0
            {
932
0
                nCenY = static_cast<sal_uInt16>(aBmp.GetSizePixel().Height() - 1);
933
0
            }
934
935
            // create centered handle as default
936
0
            pRetval.reset(new sdr::overlay::OverlayBitmapEx(rPos, aBmp, nCenX, nCenY));
937
0
        }
938
0
    }
939
940
0
    return pRetval;
941
0
}
942
943
bool SdrHdl::IsHdlHit(const Point& rPnt) const
944
0
{
945
    // OVERLAYMANAGER
946
0
    basegfx::B2DPoint aPosition(rPnt.X(), rPnt.Y());
947
0
    return maOverlayGroup.isHitLogic(aPosition);
948
0
}
949
950
PointerStyle SdrHdl::GetPointer() const
951
0
{
952
0
    PointerStyle ePtr=PointerStyle::Move;
953
0
    const bool bSize=m_eKind>=SdrHdlKind::UpperLeft && m_eKind<=SdrHdlKind::LowerRight;
954
0
    const bool bRot=m_pHdlList!=nullptr && m_pHdlList->IsRotateShear();
955
0
    const bool bDis=m_pHdlList!=nullptr && m_pHdlList->IsDistortShear();
956
0
    if (bSize && m_pHdlList!=nullptr && (bRot || bDis)) {
957
0
        switch (m_eKind) {
958
0
            case SdrHdlKind::UpperLeft: case SdrHdlKind::UpperRight:
959
0
            case SdrHdlKind::LowerLeft: case SdrHdlKind::LowerRight: ePtr=bRot ? PointerStyle::Rotate : PointerStyle::RefHand; break;
960
0
            case SdrHdlKind::Left : case SdrHdlKind::Right: ePtr=PointerStyle::VShear; break;
961
0
            case SdrHdlKind::Upper: case SdrHdlKind::Lower: ePtr=PointerStyle::HShear; break;
962
0
            default:
963
0
                break;
964
0
        }
965
0
    } else {
966
        // When resizing rotated rectangles, rotate the mouse cursor slightly, too
967
0
        if (bSize && m_nRotationAngle!=0_deg100) {
968
0
            Degree100 nHdlAngle(0);
969
0
            switch (m_eKind) {
970
0
                case SdrHdlKind::LowerRight: nHdlAngle=31500_deg100; break;
971
0
                case SdrHdlKind::Lower: nHdlAngle=27000_deg100; break;
972
0
                case SdrHdlKind::LowerLeft: nHdlAngle=22500_deg100; break;
973
0
                case SdrHdlKind::Left : nHdlAngle=18000_deg100; break;
974
0
                case SdrHdlKind::UpperLeft: nHdlAngle=13500_deg100; break;
975
0
                case SdrHdlKind::Upper: nHdlAngle=9000_deg100;  break;
976
0
                case SdrHdlKind::UpperRight: nHdlAngle=4500_deg100;  break;
977
0
                case SdrHdlKind::Right: nHdlAngle=0_deg100;     break;
978
0
                default:
979
0
                    break;
980
0
            }
981
            // a little bit more (for rounding)
982
0
            nHdlAngle = NormAngle36000(nHdlAngle + m_nRotationAngle + 2249_deg100);
983
0
            nHdlAngle/=4500_deg100;
984
0
            switch (static_cast<sal_uInt8>(nHdlAngle.get())) {
985
0
                case 0: ePtr=PointerStyle::ESize;  break;
986
0
                case 1: ePtr=PointerStyle::NESize; break;
987
0
                case 2: ePtr=PointerStyle::NSize;  break;
988
0
                case 3: ePtr=PointerStyle::NWSize; break;
989
0
                case 4: ePtr=PointerStyle::WSize;  break;
990
0
                case 5: ePtr=PointerStyle::SWSize; break;
991
0
                case 6: ePtr=PointerStyle::SSize;  break;
992
0
                case 7: ePtr=PointerStyle::SESize; break;
993
0
            } // switch
994
0
        } else {
995
0
            switch (m_eKind) {
996
0
                case SdrHdlKind::UpperLeft: ePtr=PointerStyle::NWSize;  break;
997
0
                case SdrHdlKind::Upper: ePtr=PointerStyle::NSize;     break;
998
0
                case SdrHdlKind::UpperRight: ePtr=PointerStyle::NESize;  break;
999
0
                case SdrHdlKind::Left : ePtr=PointerStyle::WSize;     break;
1000
0
                case SdrHdlKind::Right: ePtr=PointerStyle::ESize;     break;
1001
0
                case SdrHdlKind::LowerLeft: ePtr=PointerStyle::SWSize;  break;
1002
0
                case SdrHdlKind::Lower: ePtr=PointerStyle::SSize;     break;
1003
0
                case SdrHdlKind::LowerRight: ePtr=PointerStyle::SESize;  break;
1004
0
                case SdrHdlKind::Poly : ePtr=PointerStyle::MovePoint; break;
1005
0
                case SdrHdlKind::Circle : ePtr=PointerStyle::Hand;      break;
1006
0
                case SdrHdlKind::Ref1 : ePtr=PointerStyle::RefHand;   break;
1007
0
                case SdrHdlKind::Ref2 : ePtr=PointerStyle::RefHand;   break;
1008
0
                case SdrHdlKind::BezierWeight : ePtr=PointerStyle::MoveBezierWeight; break;
1009
0
                case SdrHdlKind::Glue : ePtr=PointerStyle::MovePoint; break;
1010
0
                case SdrHdlKind::CustomShape1 : ePtr=PointerStyle::RefHand; break;
1011
0
                default:
1012
0
                    break;
1013
0
            }
1014
0
        }
1015
0
    }
1016
0
    return ePtr;
1017
0
}
1018
1019
bool SdrHdl::IsFocusHdl() const
1020
0
{
1021
0
    switch(m_eKind)
1022
0
    {
1023
0
        case SdrHdlKind::UpperLeft:
1024
0
        case SdrHdlKind::Upper:
1025
0
        case SdrHdlKind::UpperRight:
1026
0
        case SdrHdlKind::Left:
1027
0
        case SdrHdlKind::Right:
1028
0
        case SdrHdlKind::LowerLeft:
1029
0
        case SdrHdlKind::Lower:
1030
0
        case SdrHdlKind::LowerRight:
1031
0
        {
1032
            // if it's an activated TextEdit, it's moved to extended points
1033
0
            return !m_pHdlList || !m_pHdlList->IsMoveOutside();
1034
0
        }
1035
1036
0
        case SdrHdlKind::Move:      // handle to move object
1037
0
        case SdrHdlKind::Poly:      // selected point of polygon or curve
1038
0
        case SdrHdlKind::BezierWeight:      // weight at a curve
1039
0
        case SdrHdlKind::Circle:      // angle of circle segments, corner radius of rectangles
1040
0
        case SdrHdlKind::Ref1:      // reference point 1, e. g. center of rotation
1041
0
        case SdrHdlKind::Ref2:      // reference point 2, e. g. endpoint of reflection axis
1042
0
        case SdrHdlKind::Glue:      // gluepoint
1043
1044
        // for SJ and the CustomShapeHandles:
1045
0
        case SdrHdlKind::CustomShape1:
1046
1047
0
        case SdrHdlKind::User:
1048
0
        {
1049
0
            return true;
1050
0
        }
1051
1052
0
        default:
1053
0
        {
1054
0
            return false;
1055
0
        }
1056
0
    }
1057
0
}
1058
1059
void SdrHdl::onMouseEnter(const MouseEvent& /*rMEvt*/)
1060
0
{
1061
0
}
1062
1063
void SdrHdl::onHelpRequest()
1064
0
{
1065
0
}
1066
1067
void SdrHdl::onMouseLeave()
1068
0
{
1069
0
}
1070
1071
Bitmap SdrHdl::createGluePointBitmap()
1072
0
{
1073
0
    return ImpGetBitmap(BitmapMarkerKind::Glue_Deselected, BitmapColorIndex::LightGreen);
1074
0
}
1075
1076
void SdrHdl::insertNewlyCreatedOverlayObjectForSdrHdl(
1077
    std::unique_ptr<sdr::overlay::OverlayObject> pOverlayObject,
1078
    const sdr::contact::ObjectContact& rObjectContact,
1079
    sdr::overlay::OverlayManager& rOverlayManager)
1080
0
{
1081
    // check if we have an OverlayObject
1082
0
    if(!pOverlayObject)
1083
0
    {
1084
0
        return;
1085
0
    }
1086
1087
    // Add GridOffset for non-linear ViewToDevice transformation (calc)
1088
0
    if(nullptr != GetObj() && rObjectContact.supportsGridOffsets())
1089
0
    {
1090
0
        basegfx::B2DVector aOffset(0.0, 0.0);
1091
0
        const sdr::contact::ViewObjectContact& rVOC(GetObj()->GetViewContact().GetViewObjectContact(
1092
0
            const_cast<sdr::contact::ObjectContact&>(rObjectContact)));
1093
1094
0
        rObjectContact.calculateGridOffsetForViewObjectContact(aOffset, rVOC);
1095
1096
0
        if(!aOffset.equalZero())
1097
0
        {
1098
0
            pOverlayObject->setOffset(aOffset);
1099
0
        }
1100
0
    }
1101
1102
    // add to OverlayManager
1103
0
    rOverlayManager.add(*pOverlayObject);
1104
1105
    // add to local OverlayObjectList - ownership change (!)
1106
0
    maOverlayGroup.append(std::move(pOverlayObject));
1107
0
}
1108
1109
SdrHdlColor::SdrHdlColor(const Point& rRef, Color aCol, const Size& rSize, bool bLum)
1110
0
:   SdrHdl(rRef, SdrHdlKind::Color),
1111
0
    m_aMarkerSize(rSize),
1112
0
    m_bUseLuminance(bLum)
1113
0
{
1114
0
    if(IsUseLuminance())
1115
0
        aCol = GetLuminance(aCol);
1116
1117
    // remember color
1118
0
    m_aMarkerColor = aCol;
1119
0
}
1120
1121
SdrHdlColor::~SdrHdlColor()
1122
{
1123
}
1124
1125
void SdrHdlColor::CreateB2dIAObject()
1126
0
{
1127
    // first throw away old one
1128
0
    GetRidOfIAObject();
1129
1130
0
    if(!m_pHdlList)
1131
0
        return;
1132
1133
0
    SdrMarkView* pView = m_pHdlList->GetView();
1134
1135
0
    if(!pView || pView->areMarkHandlesHidden())
1136
0
        return;
1137
1138
0
    SdrPageView* pPageView = pView->GetSdrPageView();
1139
1140
0
    if(!pPageView)
1141
0
        return;
1142
1143
0
    for(sal_uInt32 b(0); b < pPageView->PageWindowCount(); b++)
1144
0
    {
1145
0
        const SdrPageWindow& rPageWindow = *pPageView->GetPageWindow(b);
1146
1147
0
        if(rPageWindow.GetPaintWindow().OutputToWindow())
1148
0
        {
1149
0
            const rtl::Reference< sdr::overlay::OverlayManager >& xManager = rPageWindow.GetOverlayManager();
1150
0
            if (xManager.is())
1151
0
            {
1152
0
                Bitmap aBmpCol(CreateColorDropper(m_aMarkerColor));
1153
0
                basegfx::B2DPoint aPosition(m_aPos.X(), m_aPos.Y());
1154
0
                std::unique_ptr<sdr::overlay::OverlayObject> pNewOverlayObject(new
1155
0
                    sdr::overlay::OverlayBitmapEx(
1156
0
                        aPosition,
1157
0
                        aBmpCol,
1158
0
                        static_cast<sal_uInt16>(aBmpCol.GetSizePixel().Width() - 1) >> 1,
1159
0
                        static_cast<sal_uInt16>(aBmpCol.GetSizePixel().Height() - 1) >> 1
1160
0
                    ));
1161
1162
                // OVERLAYMANAGER
1163
0
                insertNewlyCreatedOverlayObjectForSdrHdl(
1164
0
                    std::move(pNewOverlayObject),
1165
0
                    rPageWindow.GetObjectContact(),
1166
0
                    *xManager);
1167
0
            }
1168
0
        }
1169
0
    }
1170
0
}
1171
1172
Bitmap SdrHdlColor::CreateColorDropper(Color aCol)
1173
0
{
1174
    // get the Bitmap
1175
0
    VclPtr<VirtualDevice> pWrite(VclPtr<VirtualDevice>::Create());
1176
0
    pWrite->SetOutputSizePixel(m_aMarkerSize);
1177
0
    pWrite->SetBackground(aCol);
1178
0
    pWrite->Erase();
1179
1180
    // draw outer border
1181
0
    sal_Int32 nWidth = m_aMarkerSize.Width();
1182
0
    sal_Int32 nHeight = m_aMarkerSize.Height();
1183
1184
0
    pWrite->SetLineColor(COL_LIGHTGRAY);
1185
0
    pWrite->DrawLine(Point(0, 0), Point(0, nHeight - 1));
1186
0
    pWrite->DrawLine(Point(1, 0), Point(nWidth - 1, 0));
1187
0
    pWrite->SetLineColor(COL_GRAY);
1188
0
    pWrite->DrawLine(Point(1, nHeight - 1), Point(nWidth - 1, nHeight - 1));
1189
0
    pWrite->DrawLine(Point(nWidth - 1, 1), Point(nWidth - 1, nHeight - 2));
1190
1191
    // draw lighter UpperLeft
1192
0
    const Color aLightColor(
1193
0
        static_cast<sal_uInt8>(::std::min(static_cast<sal_Int16>(static_cast<sal_Int16>(aCol.GetRed()) + sal_Int16(0x0040)), sal_Int16(0x00ff))),
1194
0
        static_cast<sal_uInt8>(::std::min(static_cast<sal_Int16>(static_cast<sal_Int16>(aCol.GetGreen()) + sal_Int16(0x0040)), sal_Int16(0x00ff))),
1195
0
        static_cast<sal_uInt8>(::std::min(static_cast<sal_Int16>(static_cast<sal_Int16>(aCol.GetBlue()) + sal_Int16(0x0040)), sal_Int16(0x00ff))));
1196
0
    pWrite->SetLineColor(aLightColor);
1197
0
    pWrite->DrawLine(Point(1, 1), Point(1, nHeight - 2));
1198
0
    pWrite->DrawLine(Point(2, 1), Point(nWidth - 2, 1));
1199
1200
    // draw darker LowerRight
1201
0
    const Color aDarkColor(
1202
0
        static_cast<sal_uInt8>(::std::max(static_cast<sal_Int16>(static_cast<sal_Int16>(aCol.GetRed()) - sal_Int16(0x0040)), sal_Int16(0x0000))),
1203
0
        static_cast<sal_uInt8>(::std::max(static_cast<sal_Int16>(static_cast<sal_Int16>(aCol.GetGreen()) - sal_Int16(0x0040)), sal_Int16(0x0000))),
1204
0
        static_cast<sal_uInt8>(::std::max(static_cast<sal_Int16>(static_cast<sal_Int16>(aCol.GetBlue()) - sal_Int16(0x0040)), sal_Int16(0x0000))));
1205
0
    pWrite->SetLineColor(aDarkColor);
1206
0
    pWrite->DrawLine(Point(2, nHeight - 2), Point(nWidth - 2, nHeight - 2));
1207
0
    pWrite->DrawLine(Point(nWidth - 2, 2), Point(nWidth - 2, nHeight - 3));
1208
1209
0
    return pWrite->GetBitmap(Point(0,0), m_aMarkerSize);
1210
0
}
1211
1212
Color SdrHdlColor::GetLuminance(const Color& rCol)
1213
0
{
1214
0
    sal_uInt8 aLum = rCol.GetLuminance();
1215
0
    Color aRetval(aLum, aLum, aLum);
1216
0
    return aRetval;
1217
0
}
1218
1219
void SdrHdlColor::SetColor(Color aNew, bool bCallLink)
1220
0
{
1221
0
    if(IsUseLuminance())
1222
0
        aNew = GetLuminance(aNew);
1223
1224
0
    if(m_aMarkerColor != aNew)
1225
0
    {
1226
        // remember new color
1227
0
        m_aMarkerColor = aNew;
1228
1229
        // create new display
1230
0
        Touch();
1231
1232
        // tell about change
1233
0
        if(bCallLink)
1234
0
            m_aColorChangeHdl.Call(this);
1235
0
    }
1236
0
}
1237
1238
void SdrHdlColor::SetSize(const Size& rNew)
1239
0
{
1240
0
    if(rNew != m_aMarkerSize)
1241
0
    {
1242
        // remember new size
1243
0
        m_aMarkerSize = rNew;
1244
1245
        // create new display
1246
0
        Touch();
1247
0
    }
1248
0
}
1249
1250
SdrHdlGradient::SdrHdlGradient(const Point& rRef1, const Point& rRef2, bool bGrad)
1251
0
    : SdrHdl(rRef1, bGrad ? SdrHdlKind::Gradient : SdrHdlKind::Transparence)
1252
0
    , m_pColHdl1(nullptr)
1253
0
    , m_pColHdl2(nullptr)
1254
0
    , m_a2ndPos(rRef2)
1255
0
    , m_bGradient(bGrad)
1256
0
    , m_bMoveSingleHandle(false)
1257
0
    , m_bMoveFirstHandle(false)
1258
0
{
1259
0
}
1260
1261
SdrHdlGradient::~SdrHdlGradient()
1262
{
1263
}
1264
1265
void SdrHdlGradient::Set2ndPos(const Point& rPnt)
1266
0
{
1267
0
    if(m_a2ndPos != rPnt)
1268
0
    {
1269
        // remember new position
1270
0
        m_a2ndPos = rPnt;
1271
1272
        // create new display
1273
0
        Touch();
1274
0
    }
1275
0
}
1276
1277
void SdrHdlGradient::CreateB2dIAObject()
1278
0
{
1279
    // first throw away old one
1280
0
    GetRidOfIAObject();
1281
1282
0
    if(!m_pHdlList)
1283
0
        return;
1284
1285
0
    SdrMarkView* pView = m_pHdlList->GetView();
1286
1287
0
    if(!pView || pView->areMarkHandlesHidden())
1288
0
        return;
1289
1290
0
    SdrPageView* pPageView = pView->GetSdrPageView();
1291
1292
0
    if(!pPageView)
1293
0
        return;
1294
1295
0
    for(sal_uInt32 b(0); b < pPageView->PageWindowCount(); b++)
1296
0
    {
1297
0
        const SdrPageWindow& rPageWindow = *pPageView->GetPageWindow(b);
1298
1299
0
        if(rPageWindow.GetPaintWindow().OutputToWindow())
1300
0
        {
1301
0
            const rtl::Reference< sdr::overlay::OverlayManager >& xManager = rPageWindow.GetOverlayManager();
1302
0
            if (xManager.is())
1303
0
            {
1304
                // striped line in between
1305
0
                basegfx::B2DVector aVec(m_a2ndPos.X() - m_aPos.X(), m_a2ndPos.Y() - m_aPos.Y());
1306
0
                double fVecLen = aVec.getLength();
1307
0
                double fLongPercentArrow = (1.0 - 0.05) * fVecLen;
1308
0
                double fHalfArrowWidth = (0.05 * 0.5) * fVecLen;
1309
0
                aVec.normalize();
1310
0
                basegfx::B2DVector aPerpend(-aVec.getY(), aVec.getX());
1311
0
                sal_Int32 nMidX = static_cast<sal_Int32>(m_aPos.X() + aVec.getX() * fLongPercentArrow);
1312
0
                sal_Int32 nMidY = static_cast<sal_Int32>(m_aPos.Y() + aVec.getY() * fLongPercentArrow);
1313
0
                Point aMidPoint(nMidX, nMidY);
1314
1315
0
                basegfx::B2DPoint aPosition(m_aPos.X(), m_aPos.Y());
1316
0
                basegfx::B2DPoint aMidPos(aMidPoint.X(), aMidPoint.Y());
1317
1318
0
                std::unique_ptr<sdr::overlay::OverlayObject> pNewOverlayObject(new
1319
0
                    sdr::overlay::OverlayLineStriped(
1320
0
                        aPosition, aMidPos
1321
0
                    ));
1322
1323
0
                pNewOverlayObject->setBaseColor(IsGradient() ? COL_BLACK : COL_BLUE);
1324
1325
                // OVERLAYMANAGER
1326
0
                insertNewlyCreatedOverlayObjectForSdrHdl(
1327
0
                    std::move(pNewOverlayObject),
1328
0
                    rPageWindow.GetObjectContact(),
1329
0
                    *xManager);
1330
1331
                // arrowhead
1332
0
                Point aLeft(aMidPoint.X() + static_cast<sal_Int32>(aPerpend.getX() * fHalfArrowWidth),
1333
0
                            aMidPoint.Y() + static_cast<sal_Int32>(aPerpend.getY() * fHalfArrowWidth));
1334
0
                Point aRight(aMidPoint.X() - static_cast<sal_Int32>(aPerpend.getX() * fHalfArrowWidth),
1335
0
                            aMidPoint.Y() - static_cast<sal_Int32>(aPerpend.getY() * fHalfArrowWidth));
1336
1337
0
                basegfx::B2DPoint aPositionLeft(aLeft.X(), aLeft.Y());
1338
0
                basegfx::B2DPoint aPositionRight(aRight.X(), aRight.Y());
1339
0
                basegfx::B2DPoint aPosition2(m_a2ndPos.X(), m_a2ndPos.Y());
1340
1341
0
                pNewOverlayObject.reset(new
1342
0
                    sdr::overlay::OverlayTriangle(
1343
0
                        aPositionLeft,
1344
0
                        aPosition2,
1345
0
                        aPositionRight,
1346
0
                        IsGradient() ? COL_BLACK : COL_BLUE
1347
0
                    ));
1348
1349
                // OVERLAYMANAGER
1350
0
                insertNewlyCreatedOverlayObjectForSdrHdl(
1351
0
                    std::move(pNewOverlayObject),
1352
0
                    rPageWindow.GetObjectContact(),
1353
0
                    *xManager);
1354
0
            }
1355
0
        }
1356
0
    }
1357
0
}
1358
1359
IMPL_LINK_NOARG(SdrHdlGradient, ColorChangeHdl, SdrHdlColor*, void)
1360
0
{
1361
0
    if(GetObj())
1362
0
        FromIAOToItem(GetObj(), true, true);
1363
0
}
1364
1365
void SdrHdlGradient::FromIAOToItem(SdrObject* _pObj, bool bSetItemOnObject, bool bUndo)
1366
0
{
1367
    // from IAO positions and colors to gradient
1368
0
    const SfxItemSet& rSet = _pObj->GetMergedItemSet();
1369
1370
0
    GradTransGradient aOldGradTransGradient;
1371
0
    GradTransGradient aGradTransGradient;
1372
0
    GradTransVector aGradTransVector;
1373
1374
0
    aGradTransVector.maPositionA = basegfx::B2DPoint(GetPos().X(), GetPos().Y());
1375
0
    aGradTransVector.maPositionB = basegfx::B2DPoint(Get2ndPos().X(), Get2ndPos().Y());
1376
0
    if(m_pColHdl1)
1377
0
        aGradTransVector.aCol1 = m_pColHdl1->GetColor();
1378
0
    if(m_pColHdl2)
1379
0
        aGradTransVector.aCol2 = m_pColHdl2->GetColor();
1380
1381
0
    if(IsGradient())
1382
0
        aOldGradTransGradient.aGradient = rSet.Get(XATTR_FILLGRADIENT).GetGradientValue();
1383
0
    else
1384
0
        aOldGradTransGradient.aGradient = rSet.Get(XATTR_FILLFLOATTRANSPARENCE).GetGradientValue();
1385
1386
    // transform vector data to gradient
1387
0
    GradTransformer::VecToGrad(aGradTransVector, aGradTransGradient, aOldGradTransGradient, _pObj, m_bMoveSingleHandle, m_bMoveFirstHandle);
1388
1389
0
    if(bSetItemOnObject)
1390
0
    {
1391
0
        SdrModel& rModel(_pObj->getSdrModelFromSdrObject());
1392
0
        SfxItemSet aNewSet(rModel.GetItemPool());
1393
0
        const OUString aString;
1394
1395
0
        if(IsGradient())
1396
0
        {
1397
0
            XFillGradientItem aNewGradItem(aString, aGradTransGradient.aGradient);
1398
0
            aNewSet.Put(aNewGradItem);
1399
0
        }
1400
0
        else
1401
0
        {
1402
0
            XFillFloatTransparenceItem aNewTransItem(aString, aGradTransGradient.aGradient);
1403
0
            aNewSet.Put(aNewTransItem);
1404
0
        }
1405
1406
0
        if(bUndo && rModel.IsUndoEnabled())
1407
0
        {
1408
0
            rModel.BegUndo(SvxResId(IsGradient() ? SIP_XA_FILLGRADIENT : SIP_XA_FILLTRANSPARENCE));
1409
0
            rModel.AddUndo(rModel.GetSdrUndoFactory().CreateUndoAttrObject(*_pObj));
1410
0
            rModel.EndUndo();
1411
0
        }
1412
1413
0
        m_pObj->SetMergedItemSetAndBroadcast(aNewSet);
1414
0
    }
1415
1416
    // back transformation, set values on pIAOHandle
1417
0
    GradTransformer::GradToVec(aGradTransGradient, aGradTransVector, _pObj);
1418
1419
0
    SetPos({ basegfx::fround<tools::Long>(aGradTransVector.maPositionA.getX()),
1420
0
             basegfx::fround<tools::Long>(aGradTransVector.maPositionA.getY()) });
1421
0
    Set2ndPos({ basegfx::fround<tools::Long>(aGradTransVector.maPositionB.getX()),
1422
0
                basegfx::fround<tools::Long>(aGradTransVector.maPositionB.getY()) });
1423
0
    if(m_pColHdl1)
1424
0
    {
1425
0
        m_pColHdl1->SetPos({ basegfx::fround<tools::Long>(aGradTransVector.maPositionA.getX()),
1426
0
                             basegfx::fround<tools::Long>(aGradTransVector.maPositionA.getY()) });
1427
0
        m_pColHdl1->SetColor(aGradTransVector.aCol1);
1428
0
    }
1429
0
    if(m_pColHdl2)
1430
0
    {
1431
0
        m_pColHdl2->SetPos({ basegfx::fround<tools::Long>(aGradTransVector.maPositionB.getX()),
1432
0
                             basegfx::fround<tools::Long>(aGradTransVector.maPositionB.getY()) });
1433
0
        m_pColHdl2->SetColor(aGradTransVector.aCol2);
1434
0
    }
1435
0
}
1436
1437
1438
SdrHdlLine::~SdrHdlLine() {}
1439
1440
void SdrHdlLine::CreateB2dIAObject()
1441
0
{
1442
    // first throw away old one
1443
0
    GetRidOfIAObject();
1444
1445
0
    if(!m_pHdlList)
1446
0
        return;
1447
1448
0
    SdrMarkView* pView = m_pHdlList->GetView();
1449
1450
0
    if(!(pView && !pView->areMarkHandlesHidden() && m_pHdl1 && m_pHdl2))
1451
0
        return;
1452
1453
0
    SdrPageView* pPageView = pView->GetSdrPageView();
1454
1455
0
    if(!pPageView)
1456
0
        return;
1457
1458
0
    for(sal_uInt32 b(0); b < pPageView->PageWindowCount(); b++)
1459
0
    {
1460
0
        const SdrPageWindow& rPageWindow = *pPageView->GetPageWindow(b);
1461
1462
0
        if(rPageWindow.GetPaintWindow().OutputToWindow())
1463
0
        {
1464
0
            const rtl::Reference< sdr::overlay::OverlayManager >& xManager = rPageWindow.GetOverlayManager();
1465
0
            if (xManager.is())
1466
0
            {
1467
0
                basegfx::B2DPoint aPosition1(m_pHdl1->GetPos().X(), m_pHdl1->GetPos().Y());
1468
0
                basegfx::B2DPoint aPosition2(m_pHdl2->GetPos().X(), m_pHdl2->GetPos().Y());
1469
1470
0
                std::unique_ptr<sdr::overlay::OverlayObject> pNewOverlayObject(new
1471
0
                    sdr::overlay::OverlayLineStriped(
1472
0
                        aPosition1,
1473
0
                        aPosition2
1474
0
                    ));
1475
1476
                // color(?)
1477
0
                pNewOverlayObject->setBaseColor(COL_LIGHTRED);
1478
1479
                // OVERLAYMANAGER
1480
0
                insertNewlyCreatedOverlayObjectForSdrHdl(
1481
0
                    std::move(pNewOverlayObject),
1482
0
                    rPageWindow.GetObjectContact(),
1483
0
                    *xManager);
1484
0
            }
1485
0
        }
1486
0
    }
1487
0
}
1488
1489
PointerStyle SdrHdlLine::GetPointer() const
1490
0
{
1491
0
    return PointerStyle::RefHand;
1492
0
}
1493
1494
1495
SdrHdlBezWgt::~SdrHdlBezWgt() {}
1496
1497
void SdrHdlBezWgt::CreateB2dIAObject()
1498
0
{
1499
    // call parent
1500
0
    SdrHdl::CreateB2dIAObject();
1501
1502
    // create lines
1503
0
    if(!m_pHdlList)
1504
0
        return;
1505
1506
0
    SdrMarkView* pView = m_pHdlList->GetView();
1507
1508
0
    if(!pView || pView->areMarkHandlesHidden())
1509
0
        return;
1510
1511
0
    SdrPageView* pPageView = pView->GetSdrPageView();
1512
1513
0
    if(!pPageView)
1514
0
        return;
1515
1516
0
    for(sal_uInt32 b(0); b < pPageView->PageWindowCount(); b++)
1517
0
    {
1518
0
        const SdrPageWindow& rPageWindow = *pPageView->GetPageWindow(b);
1519
1520
0
        if(rPageWindow.GetPaintWindow().OutputToWindow())
1521
0
        {
1522
0
            const rtl::Reference< sdr::overlay::OverlayManager >& xManager = rPageWindow.GetOverlayManager();
1523
0
            if (xManager.is())
1524
0
            {
1525
0
                basegfx::B2DPoint aPosition1(m_pHdl1->GetPos().X(), m_pHdl1->GetPos().Y());
1526
0
                basegfx::B2DPoint aPosition2(m_aPos.X(), m_aPos.Y());
1527
1528
0
                if(!aPosition1.equal(aPosition2))
1529
0
                {
1530
0
                    std::unique_ptr<sdr::overlay::OverlayObject> pNewOverlayObject(new
1531
0
                        sdr::overlay::OverlayLineStriped(
1532
0
                            aPosition1,
1533
0
                            aPosition2
1534
0
                        ));
1535
1536
                    // line part is not hittable
1537
0
                    pNewOverlayObject->setHittable(false);
1538
1539
                    // color(?)
1540
0
                    pNewOverlayObject->setBaseColor(COL_LIGHTBLUE);
1541
1542
                    // OVERLAYMANAGER
1543
0
                    insertNewlyCreatedOverlayObjectForSdrHdl(
1544
0
                        std::move(pNewOverlayObject),
1545
0
                        rPageWindow.GetObjectContact(),
1546
0
                        *xManager);
1547
0
                }
1548
0
            }
1549
0
        }
1550
0
    }
1551
0
}
1552
1553
1554
E3dVolumeMarker::E3dVolumeMarker(const basegfx::B2DPolyPolygon& rWireframePoly)
1555
0
{
1556
0
    m_aWireframePoly = rWireframePoly;
1557
0
}
1558
1559
void E3dVolumeMarker::CreateB2dIAObject()
1560
0
{
1561
    // create lines
1562
0
    if(!m_pHdlList)
1563
0
        return;
1564
1565
0
    SdrMarkView* pView = m_pHdlList->GetView();
1566
1567
0
    if(!pView || pView->areMarkHandlesHidden())
1568
0
        return;
1569
1570
0
    SdrPageView* pPageView = pView->GetSdrPageView();
1571
1572
0
    if(!pPageView)
1573
0
        return;
1574
1575
0
    for(sal_uInt32 b(0); b < pPageView->PageWindowCount(); b++)
1576
0
    {
1577
0
        const SdrPageWindow& rPageWindow = *pPageView->GetPageWindow(b);
1578
1579
0
        if(rPageWindow.GetPaintWindow().OutputToWindow())
1580
0
        {
1581
0
            const rtl::Reference< sdr::overlay::OverlayManager >& xManager = rPageWindow.GetOverlayManager();
1582
0
            if (xManager.is() && m_aWireframePoly.count())
1583
0
            {
1584
0
                std::unique_ptr<sdr::overlay::OverlayObject> pNewOverlayObject(new
1585
0
                    sdr::overlay::OverlayPolyPolygonStripedAndFilled(
1586
0
                        m_aWireframePoly));
1587
1588
0
                pNewOverlayObject->setBaseColor(COL_BLACK);
1589
1590
                // OVERLAYMANAGER
1591
0
                insertNewlyCreatedOverlayObjectForSdrHdl(
1592
0
                    std::move(pNewOverlayObject),
1593
0
                    rPageWindow.GetObjectContact(),
1594
0
                    *xManager);
1595
0
            }
1596
0
        }
1597
0
    }
1598
0
}
1599
1600
1601
ImpEdgeHdl::~ImpEdgeHdl()
1602
{
1603
}
1604
1605
void ImpEdgeHdl::CreateB2dIAObject()
1606
0
{
1607
0
    if(m_nObjHdlNum > 1 || !m_pObj)
1608
0
    {
1609
        // call parent
1610
0
        SdrHdl::CreateB2dIAObject();
1611
0
        return;
1612
0
    }
1613
1614
    // first throw away old one
1615
0
    GetRidOfIAObject();
1616
1617
0
    BitmapColorIndex eColIndex = BitmapColorIndex::LightCyan;
1618
0
    BitmapMarkerKind eKindOfMarker = BitmapMarkerKind::Rect_7x7;
1619
1620
0
    if(!m_pHdlList)
1621
0
        return;
1622
1623
0
    SdrMarkView* pView = m_pHdlList->GetView();
1624
1625
0
    if(!pView || pView->areMarkHandlesHidden())
1626
0
        return;
1627
1628
    // tdf#159666 Crash when table and line object are selected at the same time
1629
0
    auto pEdge = dynamic_cast<SdrEdgeObj*>(m_pObj);
1630
0
    if (!pEdge)
1631
0
        return;
1632
1633
0
    if(pEdge->GetConnectedNode(m_nObjHdlNum == 0) != nullptr)
1634
0
        eColIndex = BitmapColorIndex::LightRed;
1635
1636
0
    if(m_nPPntNum < 2)
1637
0
    {
1638
        // Handle with plus sign inside
1639
0
        eKindOfMarker = BitmapMarkerKind::Circ_7x7;
1640
0
    }
1641
1642
0
    SdrPageView* pPageView = pView->GetSdrPageView();
1643
0
    if(!pPageView)
1644
0
        return;
1645
1646
0
    for(sal_uInt32 b(0); b < pPageView->PageWindowCount(); b++)
1647
0
    {
1648
0
        const SdrPageWindow& rPageWindow = *pPageView->GetPageWindow(b);
1649
1650
0
        if(rPageWindow.GetPaintWindow().OutputToWindow())
1651
0
        {
1652
0
            const rtl::Reference< sdr::overlay::OverlayManager >& xManager = rPageWindow.GetOverlayManager();
1653
0
            if (xManager.is())
1654
0
            {
1655
0
                basegfx::B2DPoint aPosition(m_aPos.X(), m_aPos.Y());
1656
0
                std::unique_ptr<sdr::overlay::OverlayObject> pNewOverlayObject(CreateOverlayObject(
1657
0
                    aPosition,
1658
0
                    eColIndex,
1659
0
                    eKindOfMarker));
1660
1661
                // OVERLAYMANAGER
1662
0
                insertNewlyCreatedOverlayObjectForSdrHdl(
1663
0
                    std::move(pNewOverlayObject),
1664
0
                    rPageWindow.GetObjectContact(),
1665
0
                    *xManager);
1666
0
            }
1667
0
        }
1668
0
    }
1669
0
}
1670
1671
void ImpEdgeHdl::SetLineCode(SdrEdgeLineCode eCode)
1672
0
{
1673
0
    if(m_eLineCode != eCode)
1674
0
    {
1675
        // remember new value
1676
0
        m_eLineCode = eCode;
1677
1678
        // create new display
1679
0
        Touch();
1680
0
    }
1681
0
}
1682
1683
PointerStyle ImpEdgeHdl::GetPointer() const
1684
0
{
1685
0
    SdrEdgeObj* pEdge=dynamic_cast<SdrEdgeObj*>( m_pObj );
1686
0
    if (pEdge==nullptr)
1687
0
        return SdrHdl::GetPointer();
1688
0
    if (m_nObjHdlNum<=1)
1689
0
        return PointerStyle::MovePoint;
1690
0
    if (IsHorzDrag())
1691
0
        return PointerStyle::ESize;
1692
0
    else
1693
0
        return PointerStyle::SSize;
1694
0
}
1695
1696
bool ImpEdgeHdl::IsHorzDrag() const
1697
0
{
1698
0
    SdrEdgeObj* pEdge=dynamic_cast<SdrEdgeObj*>( m_pObj );
1699
0
    if (pEdge==nullptr)
1700
0
        return false;
1701
0
    if (m_nObjHdlNum<=1)
1702
0
        return false;
1703
1704
0
    SdrEdgeKind eEdgeKind = pEdge->GetObjectItem(SDRATTR_EDGEKIND).GetValue();
1705
1706
0
    const SdrEdgeInfoRec& rInfo=pEdge->m_aEdgeInfo;
1707
0
    if (eEdgeKind==SdrEdgeKind::OrthoLines || eEdgeKind==SdrEdgeKind::Bezier)
1708
0
    {
1709
0
        return !rInfo.ImpIsHorzLine(m_eLineCode,*pEdge->m_pEdgeTrack);
1710
0
    }
1711
0
    else if (eEdgeKind==SdrEdgeKind::ThreeLines)
1712
0
    {
1713
0
        tools::Long nAngle=m_nObjHdlNum==2 ? rInfo.m_nAngle1 : rInfo.m_nAngle2;
1714
0
        return nAngle==0 || nAngle==18000;
1715
0
    }
1716
0
    return false;
1717
0
}
1718
1719
1720
ImpMeasureHdl::~ImpMeasureHdl()
1721
{
1722
}
1723
1724
void ImpMeasureHdl::CreateB2dIAObject()
1725
0
{
1726
    // first throw away old one
1727
0
    GetRidOfIAObject();
1728
1729
0
    if(!m_pHdlList)
1730
0
        return;
1731
1732
0
    SdrMarkView* pView = m_pHdlList->GetView();
1733
1734
0
    if(!pView || pView->areMarkHandlesHidden())
1735
0
        return;
1736
1737
0
    BitmapColorIndex eColIndex = BitmapColorIndex::LightCyan;
1738
0
    BitmapMarkerKind eKindOfMarker = BitmapMarkerKind::Rect_9x9;
1739
1740
0
    if(m_nObjHdlNum > 1)
1741
0
    {
1742
0
        eKindOfMarker = BitmapMarkerKind::Rect_7x7;
1743
0
    }
1744
1745
0
    if(m_bSelect)
1746
0
    {
1747
0
        eColIndex = BitmapColorIndex::Cyan;
1748
0
    }
1749
1750
0
    SdrPageView* pPageView = pView->GetSdrPageView();
1751
1752
0
    if(!pPageView)
1753
0
        return;
1754
1755
0
    for(sal_uInt32 b(0); b < pPageView->PageWindowCount(); b++)
1756
0
    {
1757
0
        const SdrPageWindow& rPageWindow = *pPageView->GetPageWindow(b);
1758
1759
0
        if(rPageWindow.GetPaintWindow().OutputToWindow())
1760
0
        {
1761
0
            const rtl::Reference< sdr::overlay::OverlayManager >& xManager = rPageWindow.GetOverlayManager();
1762
0
            if (xManager.is())
1763
0
            {
1764
0
                basegfx::B2DPoint aPosition(m_aPos.X(), m_aPos.Y());
1765
0
                std::unique_ptr<sdr::overlay::OverlayObject> pNewOverlayObject(CreateOverlayObject(
1766
0
                    aPosition,
1767
0
                    eColIndex,
1768
0
                    eKindOfMarker));
1769
1770
                // OVERLAYMANAGER
1771
0
                insertNewlyCreatedOverlayObjectForSdrHdl(
1772
0
                    std::move(pNewOverlayObject),
1773
0
                    rPageWindow.GetObjectContact(),
1774
0
                    *xManager);
1775
0
            }
1776
0
        }
1777
0
    }
1778
0
}
1779
1780
PointerStyle ImpMeasureHdl::GetPointer() const
1781
0
{
1782
0
    switch (m_nObjHdlNum)
1783
0
    {
1784
0
        case 0: case 1: return PointerStyle::Hand;
1785
0
        case 2: case 3: return PointerStyle::MovePoint;
1786
0
        case 4: case 5: return SdrHdl::GetPointer(); // will then be rotated appropriately
1787
0
    } // switch
1788
0
    return PointerStyle::NotAllowed;
1789
0
}
1790
1791
1792
ImpTextframeHdl::ImpTextframeHdl(const tools::Rectangle& rRect) :
1793
0
    SdrHdl(rRect.TopLeft(),SdrHdlKind::Move),
1794
0
    maRect(rRect)
1795
0
{
1796
0
}
1797
1798
void ImpTextframeHdl::CreateB2dIAObject()
1799
0
{
1800
    // first throw away old one
1801
0
    GetRidOfIAObject();
1802
1803
0
    if(!m_pHdlList)
1804
0
        return;
1805
1806
0
    SdrMarkView* pView = m_pHdlList->GetView();
1807
1808
0
    if(!pView || pView->areMarkHandlesHidden())
1809
0
        return;
1810
1811
0
    SdrPageView* pPageView = pView->GetSdrPageView();
1812
1813
0
    if(!pPageView)
1814
0
        return;
1815
1816
0
    for(sal_uInt32 b(0); b < pPageView->PageWindowCount(); b++)
1817
0
    {
1818
0
        const SdrPageWindow& rPageWindow = *pPageView->GetPageWindow(b);
1819
1820
0
        if(rPageWindow.GetPaintWindow().OutputToWindow())
1821
0
        {
1822
0
            const rtl::Reference< sdr::overlay::OverlayManager >& xManager = rPageWindow.GetOverlayManager();
1823
0
            if (xManager.is())
1824
0
            {
1825
0
                const basegfx::B2DPoint aTopLeft(maRect.Left(), maRect.Top());
1826
0
                const basegfx::B2DPoint aBottomRight(maRect.Right(), maRect.Bottom());
1827
0
                const Color aHilightColor(SvtOptionsDrawinglayer::getHilightColor());
1828
0
                const double fTransparence(SvtOptionsDrawinglayer::GetTransparentSelectionPercent() * 0.01);
1829
1830
0
                std::unique_ptr<sdr::overlay::OverlayRectangle> pNewOverlayObject(new sdr::overlay::OverlayRectangle(
1831
0
                    aTopLeft,
1832
0
                    aBottomRight,
1833
0
                    aHilightColor,
1834
0
                    fTransparence,
1835
0
                    3.0,
1836
0
                    3.0,
1837
0
                    -toRadians(m_nRotationAngle),
1838
0
                    true)); // allow animation; the Handle is not shown at text edit time
1839
1840
0
                pNewOverlayObject->setHittable(false);
1841
1842
                // OVERLAYMANAGER
1843
0
                insertNewlyCreatedOverlayObjectForSdrHdl(
1844
0
                    std::move(pNewOverlayObject),
1845
0
                    rPageWindow.GetObjectContact(),
1846
0
                    *xManager);
1847
0
            }
1848
0
        }
1849
0
    }
1850
0
}
1851
1852
1853
static bool ImpSdrHdlListSorter(std::unique_ptr<SdrHdl> const& lhs, std::unique_ptr<SdrHdl> const& rhs)
1854
0
{
1855
0
    SdrHdlKind eKind1=lhs->GetKind();
1856
0
    SdrHdlKind eKind2=rhs->GetKind();
1857
    // Level 1: first normal handles, then Glue, then User, then Plus handles, then reference point handles
1858
0
    unsigned n1=1;
1859
0
    unsigned n2=1;
1860
0
    if (eKind1!=eKind2)
1861
0
    {
1862
0
        if (eKind1==SdrHdlKind::Ref1 || eKind1==SdrHdlKind::Ref2 || eKind1==SdrHdlKind::MirrorAxis) n1=5;
1863
0
        else if (eKind1==SdrHdlKind::Glue) n1=2;
1864
0
        else if (eKind1==SdrHdlKind::User) n1=3;
1865
0
        else if (eKind1==SdrHdlKind::SmartTag) n1=0;
1866
0
        if (eKind2==SdrHdlKind::Ref1 || eKind2==SdrHdlKind::Ref2 || eKind2==SdrHdlKind::MirrorAxis) n2=5;
1867
0
        else if (eKind2==SdrHdlKind::Glue) n2=2;
1868
0
        else if (eKind2==SdrHdlKind::User) n2=3;
1869
0
        else if (eKind2==SdrHdlKind::SmartTag) n2=0;
1870
0
    }
1871
0
    if (lhs->IsPlusHdl()) n1=4;
1872
0
    if (rhs->IsPlusHdl()) n2=4;
1873
0
    if (n1==n2)
1874
0
    {
1875
        // Level 2: PageView (Pointer)
1876
0
        SdrPageView* pPV1=lhs->GetPageView();
1877
0
        SdrPageView* pPV2=rhs->GetPageView();
1878
0
        if (pPV1==pPV2)
1879
0
        {
1880
            // Level 3: Position (x+y)
1881
0
            SdrObject* pObj1=lhs->GetObj();
1882
0
            SdrObject* pObj2=rhs->GetObj();
1883
0
            if (pObj1==pObj2)
1884
0
            {
1885
0
                sal_uInt32 nNum1=lhs->GetObjHdlNum();
1886
0
                sal_uInt32 nNum2=rhs->GetObjHdlNum();
1887
0
                if (nNum1==nNum2)
1888
0
                {
1889
0
                    if (eKind1==eKind2)
1890
0
                        return lhs<rhs; // Hack, to always get to the same sorting
1891
0
                    return static_cast<sal_uInt16>(eKind1)<static_cast<sal_uInt16>(eKind2);
1892
0
                }
1893
0
                else
1894
0
                    return nNum1<nNum2;
1895
0
            }
1896
0
            else
1897
0
            {
1898
0
                return pObj1<pObj2;
1899
0
            }
1900
0
        }
1901
0
        else
1902
0
        {
1903
0
            return pPV1<pPV2;
1904
0
        }
1905
0
    }
1906
0
    else
1907
0
    {
1908
0
        return n1<n2;
1909
0
    }
1910
0
}
1911
1912
namespace {
1913
1914
// Helper struct for re-sorting handles
1915
struct ImplHdlAndIndex
1916
{
1917
    SdrHdl*                     mpHdl;
1918
    sal_uInt32                  mnIndex;
1919
};
1920
1921
}
1922
1923
extern "C" {
1924
1925
// Helper method for sorting handles taking care of OrdNums, keeping order in
1926
// single objects and re-sorting polygon handles intuitively
1927
static int ImplSortHdlFunc( const void* pVoid1, const void* pVoid2 )
1928
0
{
1929
0
    const ImplHdlAndIndex* p1 = static_cast<ImplHdlAndIndex const *>(pVoid1);
1930
0
    const ImplHdlAndIndex* p2 = static_cast<ImplHdlAndIndex const *>(pVoid2);
1931
1932
0
    if(p1->mpHdl->GetObj() == p2->mpHdl->GetObj())
1933
0
    {
1934
0
        if(p1->mpHdl->GetObj() && dynamic_cast<const SdrPathObj*>(p1->mpHdl->GetObj()) != nullptr)
1935
0
        {
1936
            // same object and a path object
1937
0
            if((p1->mpHdl->GetKind() == SdrHdlKind::Poly || p1->mpHdl->GetKind() == SdrHdlKind::BezierWeight)
1938
0
                && (p2->mpHdl->GetKind() == SdrHdlKind::Poly || p2->mpHdl->GetKind() == SdrHdlKind::BezierWeight))
1939
0
            {
1940
                // both handles are point or control handles
1941
0
                if(p1->mpHdl->GetPolyNum() == p2->mpHdl->GetPolyNum())
1942
0
                {
1943
0
                    if(p1->mpHdl->GetPointNum() < p2->mpHdl->GetPointNum())
1944
0
                    {
1945
0
                        return -1;
1946
0
                    }
1947
0
                    else
1948
0
                    {
1949
0
                        return 1;
1950
0
                    }
1951
0
                }
1952
0
                else if(p1->mpHdl->GetPolyNum() < p2->mpHdl->GetPolyNum())
1953
0
                {
1954
0
                    return -1;
1955
0
                }
1956
0
                else
1957
0
                {
1958
0
                    return 1;
1959
0
                }
1960
0
            }
1961
0
        }
1962
0
    }
1963
0
    else
1964
0
    {
1965
0
        if(!p1->mpHdl->GetObj())
1966
0
        {
1967
0
            return -1;
1968
0
        }
1969
0
        else if(!p2->mpHdl->GetObj())
1970
0
        {
1971
0
            return 1;
1972
0
        }
1973
0
        else
1974
0
        {
1975
            // different objects, use OrdNum for sort
1976
0
            const sal_uInt32 nOrdNum1 = p1->mpHdl->GetObj()->GetOrdNum();
1977
0
            const sal_uInt32 nOrdNum2 = p2->mpHdl->GetObj()->GetOrdNum();
1978
1979
0
            if(nOrdNum1 < nOrdNum2)
1980
0
            {
1981
0
                return -1;
1982
0
            }
1983
0
            else
1984
0
            {
1985
0
                return 1;
1986
0
            }
1987
0
        }
1988
0
    }
1989
1990
    // fallback to indices
1991
0
    if(p1->mnIndex < p2->mnIndex)
1992
0
    {
1993
0
        return -1;
1994
0
    }
1995
0
    else
1996
0
    {
1997
0
        return 1;
1998
0
    }
1999
0
}
2000
2001
}
2002
2003
void SdrHdlList::TravelFocusHdl(bool bForward)
2004
0
{
2005
    // security correction
2006
0
    if (mnFocusIndex >= GetHdlCount())
2007
0
        mnFocusIndex = SAL_MAX_SIZE;
2008
2009
0
    if(maList.empty())
2010
0
        return;
2011
2012
    // take care of old handle
2013
0
    const size_t nOldHdlNum(mnFocusIndex);
2014
0
    SdrHdl* pOld = nullptr;
2015
0
    if (nOldHdlNum < GetHdlCount())
2016
0
        pOld = GetHdl(nOldHdlNum);
2017
2018
0
    if(pOld)
2019
0
    {
2020
        // switch off old handle
2021
0
        mnFocusIndex = SAL_MAX_SIZE;
2022
0
        pOld->Touch();
2023
0
    }
2024
2025
    // allocate pointer array for sorted handle list
2026
0
    std::unique_ptr<ImplHdlAndIndex[]> pHdlAndIndex(new ImplHdlAndIndex[maList.size()]);
2027
2028
    // build sorted handle list
2029
0
    for( size_t a = 0; a < maList.size(); ++a)
2030
0
    {
2031
0
        pHdlAndIndex[a].mpHdl = maList[a].get();
2032
0
        pHdlAndIndex[a].mnIndex = a;
2033
0
    }
2034
2035
0
    qsort(pHdlAndIndex.get(), maList.size(), sizeof(ImplHdlAndIndex), ImplSortHdlFunc);
2036
2037
    // look for old num in sorted array
2038
0
    size_t nOldHdl(nOldHdlNum);
2039
2040
0
    if(nOldHdlNum != SAL_MAX_SIZE)
2041
0
    {
2042
0
        for(size_t a = 0; a < maList.size(); ++a)
2043
0
        {
2044
0
            if(pHdlAndIndex[a].mpHdl == pOld)
2045
0
            {
2046
0
                nOldHdl = a;
2047
0
                break;
2048
0
            }
2049
0
        }
2050
0
    }
2051
2052
    // build new HdlNum
2053
0
    size_t nNewHdl(nOldHdl);
2054
2055
    // do the focus travel
2056
0
    if(bForward)
2057
0
    {
2058
0
        if(nOldHdl != SAL_MAX_SIZE)
2059
0
        {
2060
0
            if(nOldHdl == maList.size() - 1)
2061
0
            {
2062
                // end forward run
2063
0
                nNewHdl = SAL_MAX_SIZE;
2064
0
            }
2065
0
            else
2066
0
            {
2067
                // simply the next handle
2068
0
                nNewHdl++;
2069
0
            }
2070
0
        }
2071
0
        else
2072
0
        {
2073
            // start forward run at first entry
2074
0
            nNewHdl = 0;
2075
0
        }
2076
0
    }
2077
0
    else
2078
0
    {
2079
0
        if(nOldHdl == SAL_MAX_SIZE)
2080
0
        {
2081
            // start backward run at last entry
2082
0
            nNewHdl = maList.size() - 1;
2083
2084
0
        }
2085
0
        else
2086
0
        {
2087
0
            if(nOldHdl == 0)
2088
0
            {
2089
                // end backward run
2090
0
                nNewHdl = SAL_MAX_SIZE;
2091
0
            }
2092
0
            else
2093
0
            {
2094
                // simply the previous handle
2095
0
                nNewHdl--;
2096
0
            }
2097
0
        }
2098
0
    }
2099
2100
    // build new HdlNum
2101
0
    sal_uIntPtr nNewHdlNum(nNewHdl);
2102
2103
    // look for old num in sorted array
2104
0
    if(nNewHdl != SAL_MAX_SIZE)
2105
0
    {
2106
0
        SdrHdl* pNew = pHdlAndIndex[nNewHdl].mpHdl;
2107
2108
0
        for(size_t a = 0; a < maList.size(); ++a)
2109
0
        {
2110
0
            if(maList[a].get() == pNew)
2111
0
            {
2112
0
                nNewHdlNum = a;
2113
0
                break;
2114
0
            }
2115
0
        }
2116
0
    }
2117
2118
    // take care of next handle
2119
0
    if(nOldHdlNum != nNewHdlNum)
2120
0
    {
2121
0
        mnFocusIndex = nNewHdlNum;
2122
0
        if (mnFocusIndex < GetHdlCount())
2123
0
        {
2124
0
            SdrHdl* pNew = GetHdl(mnFocusIndex);
2125
0
            pNew->Touch();
2126
0
        }
2127
0
    }
2128
0
}
2129
2130
SdrHdl* SdrHdlList::GetFocusHdl() const
2131
1.09M
{
2132
1.09M
    if(mnFocusIndex < GetHdlCount())
2133
0
        return GetHdl(mnFocusIndex);
2134
1.09M
    else
2135
1.09M
        return nullptr;
2136
1.09M
}
2137
2138
void SdrHdlList::SetFocusHdl(SdrHdl* pNew)
2139
0
{
2140
0
    if(!pNew)
2141
0
        return;
2142
2143
0
    SdrHdl* pActual = GetFocusHdl();
2144
2145
0
    if(pActual && pActual == pNew)
2146
0
        return;
2147
2148
0
    const size_t nNewHdlNum = GetHdlNum(pNew);
2149
2150
0
    if(nNewHdlNum != SAL_MAX_SIZE)
2151
0
    {
2152
0
        mnFocusIndex = nNewHdlNum;
2153
2154
0
        if(pActual)
2155
0
        {
2156
0
            pActual->Touch();
2157
0
        }
2158
2159
0
        pNew->Touch();
2160
0
    }
2161
0
}
2162
2163
void SdrHdlList::ResetFocusHdl()
2164
0
{
2165
0
    SdrHdl* pHdl = GetFocusHdl();
2166
2167
0
    mnFocusIndex = SAL_MAX_SIZE;
2168
2169
0
    if(pHdl)
2170
0
    {
2171
0
        pHdl->Touch();
2172
0
    }
2173
0
}
2174
2175
2176
SdrHdlList::SdrHdlList(SdrMarkView* pV)
2177
:   mnFocusIndex(SAL_MAX_SIZE),
2178
436k
    m_pView(pV)
2179
436k
{
2180
436k
    m_nHdlSize = 3;
2181
436k
    m_bRotateShear = false;
2182
436k
    m_bMoveOutside = false;
2183
436k
    m_bDistortShear = false;
2184
436k
}
2185
2186
SdrHdlList::~SdrHdlList()
2187
436k
{
2188
436k
    Clear();
2189
436k
}
2190
2191
void SdrHdlList::SetHdlSize(sal_uInt16 nSiz)
2192
87.9k
{
2193
87.9k
    if(m_nHdlSize != nSiz)
2194
87.9k
    {
2195
        // remember new value
2196
87.9k
        m_nHdlSize = nSiz;
2197
2198
        // propagate change to IAOs
2199
87.9k
        for(size_t i=0; i<GetHdlCount(); ++i)
2200
0
        {
2201
0
            SdrHdl* pHdl = GetHdl(i);
2202
0
            pHdl->Touch();
2203
0
        }
2204
87.9k
    }
2205
87.9k
}
2206
2207
void SdrHdlList::SetMoveOutside(bool bOn)
2208
0
{
2209
0
    if(m_bMoveOutside != bOn)
2210
0
    {
2211
        // remember new value
2212
0
        m_bMoveOutside = bOn;
2213
2214
        // propagate change to IAOs
2215
0
        for(size_t i=0; i<GetHdlCount(); ++i)
2216
0
        {
2217
0
            SdrHdl* pHdl = GetHdl(i);
2218
0
            pHdl->Touch();
2219
0
        }
2220
0
    }
2221
0
}
2222
2223
void SdrHdlList::SetRotateShear(bool bOn)
2224
367k
{
2225
367k
    m_bRotateShear = bOn;
2226
367k
}
2227
2228
void SdrHdlList::SetDistortShear(bool bOn)
2229
367k
{
2230
367k
    m_bDistortShear = bOn;
2231
367k
}
2232
2233
std::unique_ptr<SdrHdl> SdrHdlList::RemoveHdl(size_t nNum)
2234
0
{
2235
0
    std::unique_ptr<SdrHdl> pRetval = std::move(maList[nNum]);
2236
0
    maList.erase(maList.begin() + nNum);
2237
2238
0
    return pRetval;
2239
0
}
2240
2241
void SdrHdlList::RemoveAllByKind(SdrHdlKind eKind)
2242
0
{
2243
0
    std::erase_if(maList, [&eKind](std::unique_ptr<SdrHdl>& rItem) { return rItem->GetKind() == eKind; });
2244
0
}
2245
2246
void SdrHdlList::Clear()
2247
803k
{
2248
803k
    maList.clear();
2249
2250
803k
    m_bRotateShear=false;
2251
803k
    m_bDistortShear=false;
2252
803k
}
2253
2254
void SdrHdlList::Sort()
2255
366k
{
2256
    // remember currently focused handle
2257
366k
    SdrHdl* pPrev = GetFocusHdl();
2258
2259
366k
    std::sort( maList.begin(), maList.end(), ImpSdrHdlListSorter );
2260
2261
    // get now and compare
2262
366k
    SdrHdl* pNow = GetFocusHdl();
2263
2264
366k
    if(pPrev == pNow)
2265
366k
        return;
2266
2267
0
    if(pPrev)
2268
0
    {
2269
0
        pPrev->Touch();
2270
0
    }
2271
2272
0
    if(pNow)
2273
0
    {
2274
0
        pNow->Touch();
2275
0
    }
2276
0
}
2277
2278
size_t SdrHdlList::GetHdlNum(const SdrHdl* pHdl) const
2279
0
{
2280
0
    if (pHdl==nullptr)
2281
0
        return SAL_MAX_SIZE;
2282
0
    auto it = std::find_if( maList.begin(), maList.end(),
2283
0
        [&](const std::unique_ptr<SdrHdl> & p) { return p.get() == pHdl; });
2284
0
    assert(it != maList.end());
2285
0
    if( it == maList.end() )
2286
0
        return SAL_MAX_SIZE;
2287
0
    return it - maList.begin();
2288
0
}
2289
2290
void SdrHdlList::AddHdl(std::unique_ptr<SdrHdl> pHdl)
2291
0
{
2292
0
    assert(pHdl);
2293
0
    pHdl->SetHdlList(this);
2294
0
    maList.push_back(std::move(pHdl));
2295
0
}
2296
2297
SdrHdl* SdrHdlList::IsHdlListHit(const Point& rPnt) const
2298
0
{
2299
0
    SdrHdl* pRet=nullptr;
2300
0
    const size_t nCount=GetHdlCount();
2301
0
    size_t nNum=nCount;
2302
0
    while (nNum>0 && pRet==nullptr)
2303
0
    {
2304
0
        nNum--;
2305
0
        SdrHdl* pHdl=GetHdl(nNum);
2306
0
        if (pHdl->IsHdlHit(rPnt))
2307
0
            pRet=pHdl;
2308
0
    }
2309
0
    return pRet;
2310
0
}
2311
2312
SdrHdl* SdrHdlList::GetHdl(SdrHdlKind eKind1) const
2313
0
{
2314
0
    SdrHdl* pRet=nullptr;
2315
0
    for (size_t i=0; i<GetHdlCount() && pRet==nullptr; ++i)
2316
0
    {
2317
0
        SdrHdl* pHdl=GetHdl(i);
2318
0
        if (pHdl->GetKind()==eKind1)
2319
0
            pRet=pHdl;
2320
0
    }
2321
0
    return pRet;
2322
0
}
2323
2324
void SdrHdlList::MoveTo(SdrHdlList& rOther)
2325
0
{
2326
0
    for (auto & pHdl : maList)
2327
0
        pHdl->SetHdlList(&rOther);
2328
0
    rOther.maList.insert(rOther.maList.end(),
2329
0
        std::make_move_iterator(maList.begin()), std::make_move_iterator(maList.end()));
2330
0
    maList.clear();
2331
0
}
2332
2333
SdrCropHdl::SdrCropHdl(
2334
    const Point& rPnt,
2335
    SdrHdlKind eNewKind,
2336
    double fShearX,
2337
    double fRotation)
2338
0
:   SdrHdl(rPnt, eNewKind),
2339
0
    mfShearX(fShearX),
2340
0
    mfRotation(fRotation)
2341
0
{
2342
0
}
2343
2344
2345
Bitmap SdrCropHdl::GetBitmapForHandle( const Bitmap& rBitmap, int nSize )
2346
0
{
2347
0
    int nPixelSize = 0, nX = 0, nY = 0, nOffset = 0;
2348
2349
0
    if( nSize <= 3 )
2350
0
    {
2351
0
        nPixelSize = 13;
2352
0
        nOffset = 0;
2353
0
    }
2354
0
    else if( nSize <=4 )
2355
0
    {
2356
0
        nPixelSize = 17;
2357
0
        nOffset = 39;
2358
0
    }
2359
0
    else
2360
0
    {
2361
0
        nPixelSize = 21;
2362
0
        nOffset = 90;
2363
0
    }
2364
2365
0
    switch( m_eKind )
2366
0
    {
2367
0
        case SdrHdlKind::UpperLeft: nX = 0; nY = 0; break;
2368
0
        case SdrHdlKind::Upper: nX = 1; nY = 0; break;
2369
0
        case SdrHdlKind::UpperRight: nX = 2; nY = 0; break;
2370
0
        case SdrHdlKind::Left:  nX = 0; nY = 1; break;
2371
0
        case SdrHdlKind::Right: nX = 2; nY = 1; break;
2372
0
        case SdrHdlKind::LowerLeft: nX = 0; nY = 2; break;
2373
0
        case SdrHdlKind::Lower: nX = 1; nY = 2; break;
2374
0
        case SdrHdlKind::LowerRight: nX = 2; nY = 2; break;
2375
0
        default: break;
2376
0
    }
2377
2378
0
    tools::Rectangle aSourceRect( Point( nX * nPixelSize + nOffset,  nY * nPixelSize), Size(nPixelSize, nPixelSize) );
2379
2380
0
    Bitmap aRetval(rBitmap);
2381
0
    aRetval.Crop(aSourceRect);
2382
0
    return aRetval;
2383
0
}
2384
2385
2386
void SdrCropHdl::CreateB2dIAObject()
2387
0
{
2388
    // first throw away old one
2389
0
    GetRidOfIAObject();
2390
2391
0
    SdrMarkView* pView = m_pHdlList ? m_pHdlList->GetView() : nullptr;
2392
0
    SdrPageView* pPageView = pView ? pView->GetSdrPageView() : nullptr;
2393
2394
0
    if( !pPageView || pView->areMarkHandlesHidden() )
2395
0
        return;
2396
2397
0
    const StyleSettings& rStyleSettings = Application::GetSettings().GetStyleSettings();
2398
0
    int nHdlSize = m_pHdlList->GetHdlSize();
2399
2400
0
    const Bitmap aHandlesBitmap(SIP_SA_CROP_MARKERS);
2401
0
    Bitmap aBmp1( GetBitmapForHandle( aHandlesBitmap, nHdlSize ) );
2402
2403
0
    for(sal_uInt32 b(0); b < pPageView->PageWindowCount(); b++)
2404
0
    {
2405
0
        const SdrPageWindow& rPageWindow = *pPageView->GetPageWindow(b);
2406
2407
0
        if(rPageWindow.GetPaintWindow().OutputToWindow())
2408
0
        {
2409
0
            const rtl::Reference< sdr::overlay::OverlayManager >& xManager = rPageWindow.GetOverlayManager();
2410
0
            if (xManager.is())
2411
0
            {
2412
0
                basegfx::B2DPoint aPosition(m_aPos.X(), m_aPos.Y());
2413
2414
0
                std::unique_ptr<sdr::overlay::OverlayObject> pOverlayObject;
2415
2416
                // animate focused handles
2417
0
                if(IsFocusHdl() && (m_pHdlList->GetFocusHdl() == this))
2418
0
                {
2419
0
                    if( nHdlSize >= 2 )
2420
0
                        nHdlSize = 1;
2421
2422
0
                    Bitmap aBmp2( GetBitmapForHandle( aHandlesBitmap, nHdlSize + 1 ) );
2423
2424
0
                    const sal_uInt64 nBlinkTime = rStyleSettings.GetCursorBlinkTime();
2425
2426
0
                    pOverlayObject.reset(new sdr::overlay::OverlayAnimatedBitmapEx(
2427
0
                        aPosition,
2428
0
                        aBmp1,
2429
0
                        aBmp2,
2430
0
                        nBlinkTime,
2431
0
                        static_cast<sal_uInt16>(aBmp1.GetSizePixel().Width() - 1) >> 1,
2432
0
                        static_cast<sal_uInt16>(aBmp1.GetSizePixel().Height() - 1) >> 1,
2433
0
                        static_cast<sal_uInt16>(aBmp2.GetSizePixel().Width() - 1) >> 1,
2434
0
                        static_cast<sal_uInt16>(aBmp2.GetSizePixel().Height() - 1) >> 1,
2435
0
                        mfShearX,
2436
0
                        mfRotation));
2437
0
                }
2438
0
                else
2439
0
                {
2440
                    // create centered handle as default
2441
0
                    pOverlayObject.reset(new sdr::overlay::OverlayBitmapEx(
2442
0
                        aPosition,
2443
0
                        aBmp1,
2444
0
                        static_cast<sal_uInt16>(aBmp1.GetSizePixel().Width() - 1) >> 1,
2445
0
                        static_cast<sal_uInt16>(aBmp1.GetSizePixel().Height() - 1) >> 1,
2446
0
                        0.0,
2447
0
                        mfShearX,
2448
0
                        mfRotation));
2449
0
                }
2450
2451
                // OVERLAYMANAGER
2452
0
                insertNewlyCreatedOverlayObjectForSdrHdl(
2453
0
                    std::move(pOverlayObject),
2454
0
                    rPageWindow.GetObjectContact(),
2455
0
                    *xManager);
2456
0
            }
2457
0
        }
2458
0
    }
2459
0
}
2460
2461
2462
// with the correction of crop handling I could get rid of the extra mirroring flag, adapted stuff
2463
// accordingly
2464
2465
SdrCropViewHdl::SdrCropViewHdl(
2466
    basegfx::B2DHomMatrix aObjectTransform,
2467
    Graphic aGraphic,
2468
    double fCropLeft,
2469
    double fCropTop,
2470
    double fCropRight,
2471
    double fCropBottom)
2472
0
:   SdrHdl(Point(), SdrHdlKind::User),
2473
0
    maObjectTransform(std::move(aObjectTransform)),
2474
0
    maGraphic(std::move(aGraphic)),
2475
0
    mfCropLeft(fCropLeft),
2476
0
    mfCropTop(fCropTop),
2477
0
    mfCropRight(fCropRight),
2478
0
    mfCropBottom(fCropBottom)
2479
0
{
2480
0
}
2481
2482
namespace {
2483
2484
0
void translateRotationToMirroring(basegfx::B2DVector & scale, double * rotate) {
2485
0
    assert(rotate != nullptr);
2486
2487
    // detect 180 degree rotation, this is the same as mirrored in X and Y,
2488
    // thus change to mirroring. Prefer mirroring here. Use the equal call
2489
    // with getSmallValue here, the original which uses rtl::math::approxEqual
2490
    // is too correct here. Maybe this changes with enhanced precision in aw080
2491
    // to the better so that this can be reduced to the more precise call again
2492
0
    if(basegfx::fTools::equal(fabs(*rotate), M_PI, 0.000000001))
2493
0
    {
2494
0
        scale.setX(scale.getX() * -1.0);
2495
0
        scale.setY(scale.getY() * -1.0);
2496
0
        *rotate = 0.0;
2497
0
    }
2498
0
}
2499
2500
}
2501
2502
void SdrCropViewHdl::CreateB2dIAObject()
2503
0
{
2504
0
    GetRidOfIAObject();
2505
0
    SdrMarkView* pView = m_pHdlList ? m_pHdlList->GetView() : nullptr;
2506
0
    SdrPageView* pPageView = pView ? pView->GetSdrPageView() : nullptr;
2507
2508
0
    if(!pPageView || pView->areMarkHandlesHidden())
2509
0
    {
2510
0
        return;
2511
0
    }
2512
2513
    // decompose to have current translate and scale
2514
0
    basegfx::B2DVector aScale, aTranslate;
2515
0
    double fRotate, fShearX;
2516
2517
0
    maObjectTransform.decompose(aScale, aTranslate, fRotate, fShearX);
2518
2519
0
    if(aScale.equalZero())
2520
0
    {
2521
0
        return;
2522
0
    }
2523
2524
0
    translateRotationToMirroring(aScale, &fRotate);
2525
2526
    // remember mirroring, reset at Scale and adapt crop values for usage;
2527
    // mirroring can stay in the object transformation, so do not have to
2528
    // cope with it here (except later for the CroppedImage transformation,
2529
    // see below)
2530
0
    const bool bMirroredX(aScale.getX() < 0.0);
2531
0
    const bool bMirroredY(aScale.getY() < 0.0);
2532
0
    double fCropLeft(mfCropLeft);
2533
0
    double fCropTop(mfCropTop);
2534
0
    double fCropRight(mfCropRight);
2535
0
    double fCropBottom(mfCropBottom);
2536
2537
0
    if(bMirroredX)
2538
0
    {
2539
0
        aScale.setX(-aScale.getX());
2540
0
    }
2541
2542
0
    if(bMirroredY)
2543
0
    {
2544
0
        aScale.setY(-aScale.getY());
2545
0
    }
2546
2547
    // create target translate and scale
2548
0
    const basegfx::B2DVector aTargetScale(
2549
0
        aScale.getX() + fCropRight + fCropLeft,
2550
0
        aScale.getY() + fCropBottom + fCropTop);
2551
0
    const basegfx::B2DVector aTargetTranslate(
2552
0
        aTranslate.getX() - fCropLeft,
2553
0
        aTranslate.getY() - fCropTop);
2554
2555
    // create ranges to make comparisons
2556
0
    const basegfx::B2DRange aCurrentForCompare(
2557
0
        aTranslate.getX(), aTranslate.getY(),
2558
0
        aTranslate.getX() + aScale.getX(), aTranslate.getY() + aScale.getY());
2559
0
    basegfx::B2DRange aCropped(
2560
0
        aTargetTranslate.getX(), aTargetTranslate.getY(),
2561
0
        aTargetTranslate.getX() + aTargetScale.getX(), aTargetTranslate.getY() + aTargetScale.getY());
2562
2563
0
    if(aCropped.isEmpty())
2564
0
    {
2565
        // nothing to return since cropped content is completely empty
2566
0
        return;
2567
0
    }
2568
2569
0
    if(aCurrentForCompare.equal(aCropped))
2570
0
    {
2571
        // no crop at all
2572
0
        return;
2573
0
    }
2574
2575
    // back-transform to have values in unit coordinates
2576
0
    basegfx::B2DHomMatrix aBackToUnit;
2577
0
    aBackToUnit.translate(-aTranslate.getX(), -aTranslate.getY());
2578
0
    aBackToUnit.scale(
2579
0
        basegfx::fTools::equalZero(aScale.getX()) ? 1.0 : 1.0 / aScale.getX(),
2580
0
        basegfx::fTools::equalZero(aScale.getY()) ? 1.0 : 1.0 / aScale.getY());
2581
2582
    // transform cropped back to unit coordinates
2583
0
    aCropped.transform(aBackToUnit);
2584
2585
    // prepare crop PolyPolygon
2586
0
    basegfx::B2DPolygon aGraphicOutlinePolygon(
2587
0
        basegfx::utils::createPolygonFromRect(
2588
0
            aCropped));
2589
0
    basegfx::B2DPolyPolygon aCropPolyPolygon(aGraphicOutlinePolygon);
2590
2591
    // current range is unit range
2592
0
    basegfx::B2DRange aOverlap(0.0, 0.0, 1.0, 1.0);
2593
2594
0
    aOverlap.intersect(aCropped);
2595
2596
0
    if(!aOverlap.isEmpty())
2597
0
    {
2598
0
        aCropPolyPolygon.append(
2599
0
            basegfx::utils::createPolygonFromRect(
2600
0
                aOverlap));
2601
0
    }
2602
2603
    // transform to object coordinates to prepare for clip
2604
0
    aCropPolyPolygon.transform(maObjectTransform);
2605
0
    aGraphicOutlinePolygon.transform(maObjectTransform);
2606
2607
    // create cropped transformation
2608
0
    basegfx::B2DHomMatrix aCroppedTransform;
2609
2610
0
    aCroppedTransform.scale(
2611
0
        aCropped.getWidth(),
2612
0
        aCropped.getHeight());
2613
0
    aCroppedTransform.translate(
2614
0
        aCropped.getMinX(),
2615
0
        aCropped.getMinY());
2616
0
    aCroppedTransform = maObjectTransform * aCroppedTransform;
2617
2618
    // prepare graphic primitive (transformed)
2619
0
    const drawinglayer::primitive2d::Primitive2DReference aGraphic(
2620
0
        new drawinglayer::primitive2d::GraphicPrimitive2D(
2621
0
            aCroppedTransform,
2622
0
            maGraphic));
2623
2624
    // prepare outline polygon for whole graphic
2625
0
    const basegfx::BColor aHilightColor(SvtOptionsDrawinglayer::getHilightColor().getBColor());
2626
0
    const drawinglayer::primitive2d::Primitive2DReference aGraphicOutline(
2627
0
        new drawinglayer::primitive2d::PolygonHairlinePrimitive2D(
2628
0
        std::move(aGraphicOutlinePolygon),
2629
0
        aHilightColor));
2630
2631
    // combine these
2632
0
    drawinglayer::primitive2d::Primitive2DContainer aCombination { aGraphic, aGraphicOutline };
2633
2634
    // embed to MaskPrimitive2D
2635
0
    const drawinglayer::primitive2d::Primitive2DReference aMaskedGraphic(
2636
0
        new drawinglayer::primitive2d::MaskPrimitive2D(
2637
0
            std::move(aCropPolyPolygon),
2638
0
            std::move(aCombination)));
2639
2640
    // embed to UnifiedTransparencePrimitive2D
2641
0
    const drawinglayer::primitive2d::Primitive2DReference aTransparenceMaskedGraphic(
2642
0
        new drawinglayer::primitive2d::UnifiedTransparencePrimitive2D(
2643
0
            drawinglayer::primitive2d::Primitive2DContainer { aMaskedGraphic },
2644
0
            0.8));
2645
2646
0
    const drawinglayer::primitive2d::Primitive2DContainer aSequence { aTransparenceMaskedGraphic };
2647
2648
0
    for(sal_uInt32 b(0); b < pPageView->PageWindowCount(); b++)
2649
0
    {
2650
        // const SdrPageViewWinRec& rPageViewWinRec = rPageViewWinList[b];
2651
0
        const SdrPageWindow& rPageWindow = *(pPageView->GetPageWindow(b));
2652
2653
0
        if(rPageWindow.GetPaintWindow().OutputToWindow())
2654
0
        {
2655
0
            const rtl::Reference< sdr::overlay::OverlayManager >& xManager = rPageWindow.GetOverlayManager();
2656
0
            if(xManager.is())
2657
0
            {
2658
0
                std::unique_ptr<sdr::overlay::OverlayObject> pNew(new sdr::overlay::OverlayPrimitive2DSequenceObject(drawinglayer::primitive2d::Primitive2DContainer(aSequence)));
2659
2660
                // only informative object, no hit
2661
0
                pNew->setHittable(false);
2662
2663
                // OVERLAYMANAGER
2664
0
                insertNewlyCreatedOverlayObjectForSdrHdl(
2665
0
                    std::move(pNew),
2666
0
                    rPageWindow.GetObjectContact(),
2667
0
                    *xManager);
2668
0
            }
2669
0
        }
2670
0
    }
2671
0
}
2672
2673
/* vim:set shiftwidth=4 softtabstop=4 expandtab: */