Coverage Report

Created: 2026-03-31 11:00

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/libreoffice/sw/source/uibase/docvw/AnchorOverlayObject.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
#include "AnchorOverlayObject.hxx"
21
#include <SidebarWindowsConsts.hxx>
22
23
#include <swrect.hxx>
24
#include <utility>
25
#include <view.hxx>
26
#include <svx/sdrpaintwindow.hxx>
27
#include <svx/svdview.hxx>
28
#include <svx/sdr/overlay/overlaymanager.hxx>
29
#include <tools/long.hxx>
30
31
#include <sw_primitivetypes2d.hxx>
32
#include <drawinglayer/attribute/lineattribute.hxx>
33
#include <drawinglayer/attribute/strokeattribute.hxx>
34
#include <drawinglayer/primitive2d/primitivetools2d.hxx>
35
#include <drawinglayer/primitive2d/PolyPolygonColorPrimitive2D.hxx>
36
#include <drawinglayer/primitive2d/PolygonStrokePrimitive2D.hxx>
37
#include <drawinglayer/primitive2d/groupprimitive2d.hxx>
38
39
namespace sw::sidebarwindows {
40
41
namespace {
42
43
// helper class: Primitive for discrete visualisation
44
class AnchorPrimitive : public drawinglayer::primitive2d::DiscreteMetricDependentPrimitive2D
45
{
46
private:
47
    basegfx::B2DPolygon             maTriangle;
48
    basegfx::B2DPolygon             maLine;
49
    basegfx::B2DPolygon             maLineTop;
50
    const AnchorState               maAnchorState;
51
    basegfx::BColor                 maColor;
52
53
    // discrete line width
54
    double                          mfDiscreteLineWidth;
55
56
    bool                            mbLineSolid : 1;
57
58
protected:
59
    virtual drawinglayer::primitive2d::Primitive2DReference create2DDecomposition(
60
        const drawinglayer::geometry::ViewInformation2D& rViewInformation) const override;
61
62
public:
63
    AnchorPrimitive( basegfx::B2DPolygon aTriangle,
64
                     basegfx::B2DPolygon aLine,
65
                     basegfx::B2DPolygon aLineTop,
66
                     AnchorState aAnchorState,
67
                     const basegfx::BColor& rColor,
68
                     double fDiscreteLineWidth,
69
                     bool bLineSolid )
70
0
    :   maTriangle(std::move(aTriangle)),
71
0
        maLine(std::move(aLine)),
72
0
        maLineTop(std::move(aLineTop)),
73
0
        maAnchorState(aAnchorState),
74
0
        maColor(rColor),
75
0
        mfDiscreteLineWidth(fDiscreteLineWidth),
76
0
        mbLineSolid(bLineSolid)
77
0
    {}
78
79
    // data access
80
0
    const basegfx::B2DPolygon& getLine() const { return maLine; }
81
0
    const basegfx::BColor& getColor() const { return maColor; }
82
0
    bool getLineSolid() const { return mbLineSolid; }
83
84
    virtual bool operator==( const drawinglayer::primitive2d::BasePrimitive2D& rPrimitive ) const override;
85
86
    virtual sal_uInt32 getPrimitive2DID() const override;
87
};
88
89
}
90
91
drawinglayer::primitive2d::Primitive2DReference AnchorPrimitive::create2DDecomposition(
92
    const drawinglayer::geometry::ViewInformation2D& /*rViewInformation*/) const
93
0
{
94
0
    drawinglayer::primitive2d::Primitive2DContainer aContainer;
95
96
0
    if ( AnchorState::Tri == maAnchorState ||
97
0
         AnchorState::All == maAnchorState )
98
0
    {
99
        // create triangle
100
0
        const drawinglayer::primitive2d::Primitive2DReference aTriangle(
101
0
            new drawinglayer::primitive2d::PolyPolygonColorPrimitive2D(
102
0
                basegfx::B2DPolyPolygon(maTriangle),
103
0
                getColor()));
104
105
0
        aContainer.push_back(aTriangle);
106
0
    }
107
108
    // prepare view-independent LineWidth and color
109
0
    const drawinglayer::attribute::LineAttribute aLineAttribute(
110
0
        getColor(),
111
0
        mfDiscreteLineWidth * getDiscreteUnit());
112
113
0
    if ( AnchorState::All == maAnchorState )
114
0
    {
115
        // create line start
116
0
        if(getLineSolid())
117
0
        {
118
0
            const drawinglayer::primitive2d::Primitive2DReference aSolidLine(
119
0
                new drawinglayer::primitive2d::PolygonStrokePrimitive2D(
120
0
                    getLine(),
121
0
                    aLineAttribute));
122
123
0
            aContainer.push_back(aSolidLine);
124
0
        }
125
0
        else
126
0
        {
127
0
            std::vector< double > aDotDashArray;
128
0
            const double fDistance(3.0 * 15.0);
129
0
            const double fDashLen(5.0 * 15.0);
130
131
0
            aDotDashArray.push_back(fDashLen);
132
0
            aDotDashArray.push_back(fDistance);
133
134
0
            drawinglayer::attribute::StrokeAttribute aStrokeAttribute(
135
0
                std::move(aDotDashArray),
136
0
                fDistance + fDashLen);
137
138
0
            const drawinglayer::primitive2d::Primitive2DReference aStrokedLine(
139
0
                new drawinglayer::primitive2d::PolygonStrokePrimitive2D(
140
0
                    getLine(),
141
0
                    aLineAttribute,
142
0
                    std::move(aStrokeAttribute)));
143
144
0
            aContainer.push_back(aStrokedLine);
145
0
        }
146
0
    }
147
148
0
    if ( AnchorState::All == maAnchorState ||
149
0
         AnchorState::End == maAnchorState )
150
0
    {
151
        // LineTop has to be created, too, but uses no shadow, so add after
152
        // the other parts are created
153
0
        const drawinglayer::primitive2d::Primitive2DReference aLineTop(
154
0
            new drawinglayer::primitive2d::PolygonStrokePrimitive2D(
155
0
                maLineTop,
156
0
                aLineAttribute));
157
158
0
        aContainer.push_back(aLineTop);
159
0
    }
160
161
0
    return new drawinglayer::primitive2d::GroupPrimitive2D(std::move(aContainer));
162
0
}
163
164
bool AnchorPrimitive::operator==( const drawinglayer::primitive2d::BasePrimitive2D& rPrimitive ) const
165
0
{
166
0
    if(drawinglayer::primitive2d::DiscreteMetricDependentPrimitive2D::operator==(rPrimitive))
167
0
    {
168
0
        const AnchorPrimitive& rCompare = static_cast< const AnchorPrimitive& >(rPrimitive);
169
170
0
        return (maTriangle == rCompare.maTriangle
171
0
            && getLine() == rCompare.getLine()
172
0
            && maLineTop == rCompare.maLineTop
173
0
            && maAnchorState == rCompare.maAnchorState
174
0
            && getColor() == rCompare.getColor()
175
0
            && mfDiscreteLineWidth == rCompare.mfDiscreteLineWidth
176
0
            && getLineSolid() == rCompare.getLineSolid());
177
0
    }
178
179
0
    return false;
180
0
}
181
182
sal_uInt32 AnchorPrimitive::getPrimitive2DID() const
183
0
{
184
0
    return PRIMITIVE2D_ID_SWSIDEBARANCHORPRIMITIVE;
185
0
}
186
187
/*static*/ std::unique_ptr<AnchorOverlayObject> AnchorOverlayObject::CreateAnchorOverlayObject(
188
                                                       SwView const & rDocView,
189
                                                       const SwRect& aAnchorRect,
190
                                                       tools::Long aPageBorder,
191
                                                       const Point& aLineStart,
192
                                                       const Point& aLineEnd,
193
                                                       const Color& aColorAnchor )
194
0
{
195
0
    std::unique_ptr<AnchorOverlayObject> pAnchorOverlayObject;
196
0
    if ( rDocView.GetDrawView() )
197
0
    {
198
0
        SdrPaintWindow* pPaintWindow = rDocView.GetDrawView()->GetPaintWindow(0);
199
0
        if( pPaintWindow )
200
0
        {
201
0
            const rtl::Reference< sdr::overlay::OverlayManager >& xOverlayManager = pPaintWindow->GetOverlayManager();
202
203
0
            if ( xOverlayManager.is() )
204
0
            {
205
0
                pAnchorOverlayObject.reset(new AnchorOverlayObject(
206
0
                    basegfx::B2DPoint( aAnchorRect.Left() , aAnchorRect.Bottom()-5*15),
207
0
                    basegfx::B2DPoint( aAnchorRect.Left()-5*15 , aAnchorRect.Bottom()+5*15),
208
0
                    basegfx::B2DPoint( aAnchorRect.Left()+5*15 , aAnchorRect.Bottom()+5*15),
209
0
                    basegfx::B2DPoint( aAnchorRect.Left(), aAnchorRect.Bottom()+2*15),
210
0
                    basegfx::B2DPoint( aPageBorder ,aAnchorRect.Bottom()+2*15),
211
0
                    basegfx::B2DPoint( aLineStart.X(),aLineStart.Y()),
212
0
                    basegfx::B2DPoint( aLineEnd.X(),aLineEnd.Y()) ,
213
0
                    aColorAnchor));
214
0
                xOverlayManager->add(*pAnchorOverlayObject);
215
0
            }
216
0
        }
217
0
    }
218
219
0
    return pAnchorOverlayObject;
220
0
}
221
222
AnchorOverlayObject::AnchorOverlayObject( const basegfx::B2DPoint& rBasePos,
223
                                          const basegfx::B2DPoint& rSecondPos,
224
                                          const basegfx::B2DPoint& rThirdPos,
225
                                          const basegfx::B2DPoint& rFourthPos,
226
                                          const basegfx::B2DPoint& rFifthPos,
227
                                          const basegfx::B2DPoint& rSixthPos,
228
                                          const basegfx::B2DPoint& rSeventhPos,
229
                                          const Color& rBaseColor)
230
0
    : OverlayObjectWithBasePosition(rBasePos, rBaseColor)
231
0
    , maSecondPosition(rSecondPos)
232
0
    , maThirdPosition(rThirdPos)
233
0
    , maFourthPosition(rFourthPos)
234
0
    , maFifthPosition(rFifthPos)
235
0
    , maSixthPosition(rSixthPos)
236
0
    , maSeventhPosition(rSeventhPos)
237
0
    , mAnchorState(AnchorState::All)
238
0
    , mbLineSolid(false)
239
0
{
240
0
}
241
242
AnchorOverlayObject::~AnchorOverlayObject()
243
0
{
244
0
    if ( getOverlayManager() )
245
0
    {
246
        // remove this object from the chain
247
0
        getOverlayManager()->remove(*this);
248
0
    }
249
0
}
250
251
void AnchorOverlayObject::implEnsureGeometry()
252
0
{
253
0
    if(!maTriangle.count())
254
0
    {
255
0
        maTriangle.append(getBasePosition());
256
0
        maTriangle.append(GetSecondPosition());
257
0
        maTriangle.append(GetThirdPosition());
258
0
        maTriangle.setClosed(true);
259
0
    }
260
261
0
    if(!maLine.count())
262
0
    {
263
0
        maLine.append(GetFourthPosition());
264
0
        maLine.append(GetFifthPosition());
265
0
        maLine.append(GetSixthPosition());
266
0
    }
267
268
0
    if(!maLineTop.count())
269
0
    {
270
0
        maLineTop.append(GetSixthPosition());
271
0
        maLineTop.append(GetSeventhPosition());
272
0
    }
273
0
}
274
275
void AnchorOverlayObject::implResetGeometry()
276
0
{
277
0
    maTriangle.clear();
278
0
    maLine.clear();
279
0
    maLineTop.clear();
280
0
}
281
282
drawinglayer::primitive2d::Primitive2DContainer AnchorOverlayObject::createOverlayObjectPrimitive2DSequence()
283
0
{
284
0
    implEnsureGeometry();
285
286
0
    static const double aDiscreteLineWidth(1.6);
287
0
    const drawinglayer::primitive2d::Primitive2DReference aReference(
288
0
        new AnchorPrimitive( maTriangle,
289
0
                             maLine,
290
0
                             maLineTop,
291
0
                             GetAnchorState(),
292
0
                             getBaseColor().getBColor(),
293
0
                             ANCHORLINE_WIDTH * aDiscreteLineWidth,
294
0
                             getLineSolid()) );
295
296
0
    return drawinglayer::primitive2d::Primitive2DContainer { aReference };
297
0
}
298
299
void AnchorOverlayObject::SetAllPosition( const basegfx::B2DPoint& rPoint1,
300
                                          const basegfx::B2DPoint& rPoint2,
301
                                          const basegfx::B2DPoint& rPoint3,
302
                                          const basegfx::B2DPoint& rPoint4,
303
                                          const basegfx::B2DPoint& rPoint5,
304
                                          const basegfx::B2DPoint& rPoint6,
305
                                          const basegfx::B2DPoint& rPoint7)
306
0
{
307
0
    if ( !(rPoint1 != getBasePosition() ||
308
0
         rPoint2 != GetSecondPosition() ||
309
0
         rPoint3 != GetThirdPosition() ||
310
0
         rPoint4 != GetFourthPosition() ||
311
0
         rPoint5 != GetFifthPosition() ||
312
0
         rPoint6 != GetSixthPosition() ||
313
0
         rPoint7 != GetSeventhPosition()) )
314
0
        return;
315
316
0
    maBasePosition = rPoint1;
317
0
    maSecondPosition = rPoint2;
318
0
    maThirdPosition = rPoint3;
319
0
    maFourthPosition = rPoint4;
320
0
    maFifthPosition = rPoint5;
321
0
    maSixthPosition = rPoint6;
322
0
    maSeventhPosition = rPoint7;
323
324
0
    implResetGeometry();
325
0
    objectChange();
326
0
}
327
328
void AnchorOverlayObject::SetSixthPosition(const basegfx::B2DPoint& rNew)
329
0
{
330
0
  if(rNew != maSixthPosition)
331
0
  {
332
0
      maSixthPosition = rNew;
333
0
      implResetGeometry();
334
0
      objectChange();
335
0
  }
336
0
}
337
338
void AnchorOverlayObject::SetSeventhPosition(const basegfx::B2DPoint& rNew)
339
0
{
340
0
  if(rNew != maSeventhPosition)
341
0
  {
342
0
      maSeventhPosition = rNew;
343
0
      implResetGeometry();
344
0
      objectChange();
345
0
  }
346
0
}
347
348
void AnchorOverlayObject::SetTriPosition(const basegfx::B2DPoint& rPoint1,const basegfx::B2DPoint& rPoint2,const basegfx::B2DPoint& rPoint3,
349
                                  const basegfx::B2DPoint& rPoint4,const basegfx::B2DPoint& rPoint5)
350
0
{
351
0
    if(rPoint1 != getBasePosition()
352
0
        || rPoint2 != GetSecondPosition()
353
0
        || rPoint3 != GetThirdPosition()
354
0
        || rPoint4 != GetFourthPosition()
355
0
        || rPoint5 != GetFifthPosition())
356
0
    {
357
0
      maBasePosition = rPoint1;
358
0
      maSecondPosition = rPoint2;
359
0
      maThirdPosition = rPoint3;
360
0
      maFourthPosition = rPoint4;
361
0
      maFifthPosition = rPoint5;
362
363
0
      implResetGeometry();
364
0
      objectChange();
365
0
    }
366
0
}
367
368
void AnchorOverlayObject::setLineSolid( const bool bNew )
369
0
{
370
0
  if ( bNew != getLineSolid() )
371
0
  {
372
0
      mbLineSolid = bNew;
373
0
      objectChange();
374
0
  }
375
0
}
376
377
void AnchorOverlayObject::SetAnchorState( const AnchorState aState)
378
0
{
379
0
  if ( mAnchorState != aState)
380
0
  {
381
0
      mAnchorState = aState;
382
0
      objectChange();
383
0
  }
384
0
}
385
386
} // end of namespace sw::sidebarwindows
387
388
/* vim:set shiftwidth=4 softtabstop=4 expandtab: */