Coverage Report

Created: 2026-05-16 09:25

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/libreoffice/drawinglayer/source/primitive2d/discreteshadowprimitive2d.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 <drawinglayer/primitive2d/discreteshadowprimitive2d.hxx>
21
#include <drawinglayer/primitive2d/drawinglayer_primitivetypes2d.hxx>
22
#include <drawinglayer/primitive2d/bitmapprimitive2d.hxx>
23
#include <basegfx/matrix/b2dhommatrixtools.hxx>
24
#include <drawinglayer/primitive2d/transformprimitive2d.hxx>
25
#include <drawinglayer/geometry/viewinformation2d.hxx>
26
#include <osl/diagnose.h>
27
28
29
namespace drawinglayer::primitive2d
30
{
31
        DiscreteShadow::DiscreteShadow(const Bitmap& rBitmap)
32
0
        :   maBitmap(rBitmap)
33
0
        {
34
0
            maBitmap.Invert(); // convert transparency to alpha
35
0
            const Size aBitmapSize = getBitmap().GetSizePixel();
36
37
0
            if(aBitmapSize.Width() != aBitmapSize.Height() || aBitmapSize.Width() < 7)
38
0
            {
39
0
                OSL_ENSURE(false, "DiscreteShadowPrimitive2D: wrong bitmap format (!)");
40
0
                maBitmap = Bitmap();
41
0
            }
42
0
        }
43
44
        const Bitmap& DiscreteShadow::getTopLeft() const
45
0
        {
46
0
            if(maTopLeft.IsEmpty())
47
0
            {
48
0
                const sal_Int32 nQuarter((getBitmap().GetSizePixel().Width() - 3) >> 2);
49
0
                const_cast< DiscreteShadow* >(this)->maTopLeft = getBitmap();
50
0
                const_cast< DiscreteShadow* >(this)->maTopLeft.Crop(
51
0
                    ::tools::Rectangle(Point(0, 0), Size((nQuarter * 2) + 1, (nQuarter * 2) + 1)));
52
0
            }
53
54
0
            return maTopLeft;
55
0
        }
56
57
        const Bitmap& DiscreteShadow::getTop() const
58
0
        {
59
0
            if(maTop.IsEmpty())
60
0
            {
61
0
                const sal_Int32 nQuarter((getBitmap().GetSizePixel().Width() - 3) >> 2);
62
0
                const_cast< DiscreteShadow* >(this)->maTop = getBitmap();
63
0
                const_cast< DiscreteShadow* >(this)->maTop.Crop(
64
0
                    ::tools::Rectangle(Point((nQuarter * 2) + 1, 0), Size(1, nQuarter)));
65
0
            }
66
67
0
            return maTop;
68
0
        }
69
70
        const Bitmap& DiscreteShadow::getTopRight() const
71
0
        {
72
0
            if(maTopRight.IsEmpty())
73
0
            {
74
0
                const sal_Int32 nQuarter((getBitmap().GetSizePixel().Width() - 3) >> 2);
75
0
                const_cast< DiscreteShadow* >(this)->maTopRight = getBitmap();
76
0
                const_cast< DiscreteShadow* >(this)->maTopRight.Crop(
77
0
                    ::tools::Rectangle(Point((nQuarter * 2) + 2, 0), Size((nQuarter * 2) + 1, (nQuarter * 2) + 1)));
78
0
            }
79
80
0
            return maTopRight;
81
0
        }
82
83
        const Bitmap& DiscreteShadow::getRight() const
84
0
        {
85
0
            if(maRight.IsEmpty())
86
0
            {
87
0
                const sal_Int32 nQuarter((getBitmap().GetSizePixel().Width() - 3) >> 2);
88
0
                const_cast< DiscreteShadow* >(this)->maRight = getBitmap();
89
0
                const_cast< DiscreteShadow* >(this)->maRight.Crop(
90
0
                    ::tools::Rectangle(Point((nQuarter * 3) + 3, (nQuarter * 2) + 1), Size(nQuarter, 1)));
91
0
            }
92
93
0
            return maRight;
94
0
        }
95
96
        const Bitmap& DiscreteShadow::getBottomRight() const
97
0
        {
98
0
            if(maBottomRight.IsEmpty())
99
0
            {
100
0
                const sal_Int32 nQuarter((getBitmap().GetSizePixel().Width() - 3) >> 2);
101
0
                const_cast< DiscreteShadow* >(this)->maBottomRight = getBitmap();
102
0
                const_cast< DiscreteShadow* >(this)->maBottomRight.Crop(
103
0
                    ::tools::Rectangle(Point((nQuarter * 2) + 2, (nQuarter * 2) + 2), Size((nQuarter * 2) + 1, (nQuarter * 2) + 1)));
104
0
            }
105
106
0
            return maBottomRight;
107
0
        }
108
109
        const Bitmap& DiscreteShadow::getBottom() const
110
0
        {
111
0
            if(maBottom.IsEmpty())
112
0
            {
113
0
                const sal_Int32 nQuarter((getBitmap().GetSizePixel().Width() - 3) >> 2);
114
0
                const_cast< DiscreteShadow* >(this)->maBottom = getBitmap();
115
0
                const_cast< DiscreteShadow* >(this)->maBottom.Crop(
116
0
                    ::tools::Rectangle(Point((nQuarter * 2) + 1, (nQuarter * 3) + 3), Size(1, nQuarter)));
117
0
            }
118
119
0
            return maBottom;
120
0
        }
121
122
        const Bitmap& DiscreteShadow::getBottomLeft() const
123
0
        {
124
0
            if(maBottomLeft.IsEmpty())
125
0
            {
126
0
                const sal_Int32 nQuarter((getBitmap().GetSizePixel().Width() - 3) >> 2);
127
0
                const_cast< DiscreteShadow* >(this)->maBottomLeft = getBitmap();
128
0
                const_cast< DiscreteShadow* >(this)->maBottomLeft.Crop(
129
0
                    ::tools::Rectangle(Point(0, (nQuarter * 2) + 2), Size((nQuarter * 2) + 1, (nQuarter * 2) + 1)));
130
0
            }
131
132
0
            return maBottomLeft;
133
0
        }
134
135
        const Bitmap& DiscreteShadow::getLeft() const
136
0
        {
137
0
            if(maLeft.IsEmpty())
138
0
            {
139
0
                const sal_Int32 nQuarter((getBitmap().GetSizePixel().Width() - 3) >> 2);
140
0
                const_cast< DiscreteShadow* >(this)->maLeft = getBitmap();
141
0
                const_cast< DiscreteShadow* >(this)->maLeft.Crop(
142
0
                    ::tools::Rectangle(Point(0, (nQuarter * 2) + 1), Size(nQuarter, 1)));
143
0
            }
144
145
0
            return maLeft;
146
0
        }
147
148
} // end of namespace
149
150
151
namespace drawinglayer::primitive2d
152
{
153
        Primitive2DReference DiscreteShadowPrimitive2D::create2DDecomposition(const geometry::ViewInformation2D& /*rViewInformation*/) const
154
0
        {
155
0
            Primitive2DContainer xRetval;
156
157
0
            if(getDiscreteShadow().getBitmap().IsEmpty())
158
0
                return nullptr;
159
160
0
            const sal_Int32 nQuarter((getDiscreteShadow().getBitmap().GetSizePixel().Width() - 3) >> 2);
161
0
            const basegfx::B2DVector aScale(getTransform() * basegfx::B2DVector(1.0, 1.0));
162
0
            const double fSingleX(getDiscreteUnit() / aScale.getX());
163
0
            const double fSingleY(getDiscreteUnit() / aScale.getY());
164
0
            const double fBorderX(fSingleX * nQuarter);
165
0
            const double fBorderY(fSingleY * nQuarter);
166
0
            const double fBigLenX((fBorderX * 2.0) + fSingleX);
167
0
            const double fBigLenY((fBorderY * 2.0) + fSingleY);
168
169
0
            xRetval.resize(8);
170
171
            // TopLeft
172
0
            xRetval[0] =
173
0
                new BitmapPrimitive2D(
174
0
                    getDiscreteShadow().getTopLeft(),
175
0
                    basegfx::utils::createScaleTranslateB2DHomMatrix(
176
0
                        fBigLenX,
177
0
                        fBigLenY,
178
0
                        -fBorderX,
179
0
                        -fBorderY));
180
181
            // Top
182
0
            xRetval[1] =
183
0
                new BitmapPrimitive2D(
184
0
                    getDiscreteShadow().getTop(),
185
0
                    basegfx::utils::createScaleTranslateB2DHomMatrix(
186
0
                        1.0 - (2.0 * (fBorderX + fSingleX)) + fSingleX,
187
0
                        fBorderY,
188
0
                        fBorderX + fSingleX,
189
0
                        -fBorderY));
190
191
            // TopRight
192
0
            xRetval[2] =
193
0
                new BitmapPrimitive2D(
194
0
                    getDiscreteShadow().getTopRight(),
195
0
                    basegfx::utils::createScaleTranslateB2DHomMatrix(
196
0
                        fBigLenX,
197
0
                        fBigLenY,
198
0
                        1.0 - fBorderX,
199
0
                        -fBorderY));
200
201
            // Right
202
0
            xRetval[3] =
203
0
                new BitmapPrimitive2D(
204
0
                    getDiscreteShadow().getRight(),
205
0
                    basegfx::utils::createScaleTranslateB2DHomMatrix(
206
0
                        fBorderX,
207
0
                        1.0 - (2.0 * (fBorderY + fSingleY)) + fSingleY,
208
0
                        1.0 + fSingleX,
209
0
                        fBorderY + fSingleY));
210
211
            // BottomRight
212
0
            xRetval[4] =
213
0
                new BitmapPrimitive2D(
214
0
                    getDiscreteShadow().getBottomRight(),
215
0
                    basegfx::utils::createScaleTranslateB2DHomMatrix(
216
0
                        fBigLenX,
217
0
                        fBigLenY,
218
0
                        1.0 - (fBorderX + fSingleX) + fSingleX,
219
0
                        1.0 - (fBorderY + fSingleY) + fSingleY));
220
221
            // Bottom
222
0
            xRetval[5] =
223
0
                new BitmapPrimitive2D(
224
0
                    getDiscreteShadow().getBottom(),
225
0
                    basegfx::utils::createScaleTranslateB2DHomMatrix(
226
0
                        1.0 - (2.0 * (fBorderX + fSingleX)) + fSingleX,
227
0
                        fBorderY,
228
0
                        fBorderX + fSingleX,
229
0
                        1.0 + fSingleY));
230
231
            // BottomLeft
232
0
            xRetval[6] =
233
0
                new BitmapPrimitive2D(
234
0
                    getDiscreteShadow().getBottomLeft(),
235
0
                    basegfx::utils::createScaleTranslateB2DHomMatrix(
236
0
                        fBigLenX,
237
0
                        fBigLenY,
238
0
                        -fBorderX,
239
0
                        1.0 - fBorderY));
240
241
            // Left
242
0
            xRetval[7] =
243
0
                new BitmapPrimitive2D(
244
0
                    getDiscreteShadow().getLeft(),
245
0
                    basegfx::utils::createScaleTranslateB2DHomMatrix(
246
0
                        fBorderX,
247
0
                        1.0 - (2.0 * (fBorderY + fSingleY)) + fSingleY,
248
0
                        -fBorderX,
249
0
                        fBorderY + fSingleY));
250
251
            // put all in object transformation to get to target positions
252
0
            return
253
0
                new TransformPrimitive2D(
254
0
                    getTransform(),
255
0
                    std::move(xRetval));
256
0
        }
257
258
        DiscreteShadowPrimitive2D::DiscreteShadowPrimitive2D(
259
            const basegfx::B2DHomMatrix& rTransform,
260
            const DiscreteShadow& rDiscreteShadow)
261
0
        :   maTransform(rTransform),
262
0
            maDiscreteShadow(rDiscreteShadow)
263
0
        {
264
0
        }
265
266
        bool DiscreteShadowPrimitive2D::operator==(const BasePrimitive2D& rPrimitive) const
267
0
        {
268
0
            if(DiscreteMetricDependentPrimitive2D::operator==(rPrimitive))
269
0
            {
270
0
                const DiscreteShadowPrimitive2D& rCompare = static_cast<const DiscreteShadowPrimitive2D&>(rPrimitive);
271
272
0
                return (getTransform() == rCompare.getTransform()
273
0
                    && getDiscreteShadow() == rCompare.getDiscreteShadow());
274
0
            }
275
276
0
            return false;
277
0
        }
278
279
        basegfx::B2DRange DiscreteShadowPrimitive2D::getB2DRange(const geometry::ViewInformation2D& rViewInformation) const
280
0
        {
281
0
            if(getDiscreteShadow().getBitmap().IsEmpty())
282
0
            {
283
                // no graphics without valid bitmap definition
284
0
                return basegfx::B2DRange();
285
0
            }
286
0
            else
287
0
            {
288
                // prepare normal objectrange
289
0
                basegfx::B2DRange aRetval(0.0, 0.0, 1.0, 1.0);
290
0
                aRetval.transform(getTransform());
291
292
                // extract discrete shadow size and grow
293
0
                const basegfx::B2DVector aScale(rViewInformation.getViewTransformation() * basegfx::B2DVector(1.0, 1.0));
294
0
                const sal_Int32 nQuarter((getDiscreteShadow().getBitmap().GetSizePixel().Width() - 3) >> 2);
295
0
                const double fGrowX((1.0 / aScale.getX()) * nQuarter);
296
0
                const double fGrowY((1.0 / aScale.getY()) * nQuarter);
297
0
                aRetval.grow(std::max(fGrowX, fGrowY));
298
299
0
                return aRetval;
300
0
            }
301
0
        }
302
303
        // provide unique ID
304
        sal_uInt32 DiscreteShadowPrimitive2D::getPrimitive2DID() const
305
0
        {
306
0
            return PRIMITIVE2D_ID_DISCRETESHADOWPRIMITIVE2D;
307
0
        }
308
309
} // end of namespace
310
311
/* vim:set shiftwidth=4 softtabstop=4 expandtab: */