Coverage Report

Created: 2025-12-31 10:39

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/libreoffice/include/basegfx/raster/rasterconvert3d.hxx
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
#pragma once
21
22
#include <config_options.h>
23
#include <sal/types.h>
24
#include <cassert>
25
#include <vector>
26
27
#include <basegfx/color/bcolor.hxx>
28
#include <basegfx/vector/b3dvector.hxx>
29
#include <basegfx/point/b2dpoint.hxx>
30
#include <basegfx/basegfxdllapi.h>
31
32
namespace basegfx
33
{
34
    class B3DPolygon;
35
    class B3DPolyPolygon;
36
}
37
38
// interpolators for double precision
39
40
namespace basegfx
41
{
42
    class ip_single
43
    {
44
    private:
45
        double                                      mfVal;
46
        double                                      mfInc;
47
48
    public:
49
        ip_single()
50
0
        :   mfVal(0.0),
51
0
            mfInc(0.0)
52
0
        {}
53
54
        ip_single(double fVal, double fInc)
55
0
        :   mfVal(fVal),
56
0
            mfInc(fInc)
57
0
        {}
58
59
0
        double getVal() const { return mfVal; }
60
0
        double getInc() const { return mfInc; }
61
62
0
        void increment(double fStep) { mfVal += fStep * mfInc; }
63
    };
64
65
    class ip_double
66
    {
67
    private:
68
        ip_single                                   maX;
69
        ip_single                                   maY;
70
71
    public:
72
        ip_double()
73
0
        {}
74
75
        ip_double(double fXVal, double fXInc, double fYVal, double fYInc)
76
0
        :   maX(fXVal, fXInc),
77
0
            maY(fYVal, fYInc)
78
0
        {}
79
80
0
        const ip_single& getX() const { return maX; }
81
0
        const ip_single& getY() const { return maY; }
82
83
0
        void increment(double fStep) { maX.increment(fStep); maY.increment(fStep); }
84
    };
85
86
    class ip_triple
87
    {
88
    private:
89
        ip_single                                   maX;
90
        ip_single                                   maY;
91
        ip_single                                   maZ;
92
93
    public:
94
        ip_triple()
95
0
        {}
96
97
        ip_triple(double fXVal, double fXInc, double fYVal, double fYInc, double fZVal, double fZInc)
98
0
        :   maX(fXVal, fXInc),
99
0
            maY(fYVal, fYInc),
100
0
            maZ(fZVal, fZInc)
101
0
        {}
102
103
0
        const ip_single& getX() const { return maX; }
104
0
        const ip_single& getY() const { return maY; }
105
0
        const ip_single& getZ() const { return maZ; }
106
107
0
        void increment(double fStep) { maX.increment(fStep); maY.increment(fStep); maZ.increment(fStep); }
108
    };
109
110
    // InterpolatorProvider3D to have a common source for allocating interpolators
111
    // which may then be addressed using the index to the vectors
112
113
0
    #define SCANLINE_EMPTY_INDEX (0xffffffff)
114
115
    class InterpolatorProvider3D
116
    {
117
    private:
118
        ::std::vector< ip_triple >                  maColorInterpolators;
119
        ::std::vector< ip_triple >                  maNormalInterpolators;
120
        ::std::vector< ip_double >                  maTextureInterpolators;
121
        ::std::vector< ip_triple >                  maInverseTextureInterpolators;
122
123
    protected:
124
        sal_uInt32 addColorInterpolator(const BColor& rA, const BColor& rB, double fInvYDelta)
125
0
        {
126
0
            double aDeltaRed(rB.getRed() - rA.getRed());
127
128
0
            if(fTools::equalZero(aDeltaRed))
129
0
            {
130
0
                aDeltaRed = 0.0;
131
0
            }
132
0
            else
133
0
            {
134
0
                aDeltaRed *= fInvYDelta;
135
0
            }
136
137
0
            double aDeltaGreen(rB.getGreen() - rA.getGreen());
138
139
0
            if(fTools::equalZero(aDeltaGreen))
140
0
            {
141
0
                aDeltaGreen = 0.0;
142
0
            }
143
0
            else
144
0
            {
145
0
                aDeltaGreen *= fInvYDelta;
146
0
            }
147
148
0
            double aDeltaBlue(rB.getBlue() - rA.getBlue());
149
150
0
            if(fTools::equalZero(aDeltaBlue))
151
0
            {
152
0
                aDeltaBlue = 0.0;
153
0
            }
154
0
            else
155
0
            {
156
0
                aDeltaBlue *= fInvYDelta;
157
0
            }
158
159
0
            maColorInterpolators.push_back(
160
0
                ip_triple(
161
0
                    rA.getRed(), aDeltaRed,
162
0
                    rA.getGreen(), aDeltaGreen,
163
0
                    rA.getBlue(), aDeltaBlue));
164
165
0
            return (maColorInterpolators.size() - 1);
166
0
        }
167
168
        sal_uInt32 addNormalInterpolator(const B3DVector& rA, const B3DVector& rB, double fInvYDelta)
169
0
        {
170
0
            double aDeltaX(rB.getX() - rA.getX());
171
172
0
            if(fTools::equalZero(aDeltaX))
173
0
            {
174
0
                aDeltaX = 0.0;
175
0
            }
176
0
            else
177
0
            {
178
0
                aDeltaX *= fInvYDelta;
179
0
            }
180
181
0
            double aDeltaY(rB.getY() - rA.getY());
182
183
0
            if(fTools::equalZero(aDeltaY))
184
0
            {
185
0
                aDeltaY = 0.0;
186
0
            }
187
0
            else
188
0
            {
189
0
                aDeltaY *= fInvYDelta;
190
0
            }
191
192
0
            double aDeltaZ(rB.getZ() - rA.getZ());
193
194
0
            if(fTools::equalZero(aDeltaZ))
195
0
            {
196
0
                aDeltaZ = 0.0;
197
0
            }
198
0
            else
199
0
            {
200
0
                aDeltaZ *= fInvYDelta;
201
0
            }
202
203
0
            maNormalInterpolators.push_back(
204
0
                ip_triple(
205
0
                    rA.getX(), aDeltaX,
206
0
                    rA.getY(), aDeltaY,
207
0
                    rA.getZ(), aDeltaZ));
208
209
0
            return (maNormalInterpolators.size() - 1);
210
0
        }
211
212
        sal_uInt32 addTextureInterpolator(const B2DPoint& rA, const B2DPoint& rB, double fInvYDelta)
213
0
        {
214
0
            double aDeltaX(rB.getX() - rA.getX());
215
216
0
            if(fTools::equalZero(aDeltaX))
217
0
            {
218
0
                aDeltaX = 0.0;
219
0
            }
220
0
            else
221
0
            {
222
0
                aDeltaX *= fInvYDelta;
223
0
            }
224
225
0
            double aDeltaY(rB.getY() - rA.getY());
226
227
0
            if(fTools::equalZero(aDeltaY))
228
0
            {
229
0
                aDeltaY = 0.0;
230
0
            }
231
0
            else
232
0
            {
233
0
                aDeltaY *= fInvYDelta;
234
0
            }
235
236
0
            maTextureInterpolators.push_back(
237
0
                ip_double(
238
0
                    rA.getX(), aDeltaX,
239
0
                    rA.getY(), aDeltaY));
240
241
0
            return (maTextureInterpolators.size() - 1);
242
0
        }
243
244
        sal_uInt32 addInverseTextureInterpolator(const B2DPoint& rA, const B2DPoint& rB, double fZEyeA, double fZEyeB, double fInvYDelta)
245
0
        {
246
0
            double fZDelta(fZEyeB - fZEyeA);
247
0
            const double fInvZEyeA(fTools::equalZero(fZEyeA) ? fZEyeA : 1.0 / fZEyeA);
248
0
            double fInvZEyeB(fInvZEyeA);
249
250
0
            if(fTools::equalZero(fZDelta))
251
0
            {
252
0
                fZDelta = 0.0;
253
0
            }
254
0
            else
255
0
            {
256
0
                fInvZEyeB = fTools::equalZero(fZEyeB) ? fZEyeB : 1.0 / fZEyeB;
257
0
                fZDelta = (fInvZEyeB - fInvZEyeA) * fInvYDelta;
258
0
            }
259
260
0
            const B2DPoint aInvA(rA * fInvZEyeA);
261
0
            const B2DPoint aInvB(rB * fInvZEyeB);
262
0
            const double aDeltaX((aInvB.getX() - aInvA.getX()) * fInvYDelta);
263
0
            const double aDeltaY((aInvB.getY() - aInvA.getY()) * fInvYDelta);
264
265
0
            maInverseTextureInterpolators.push_back(
266
0
                ip_triple(
267
0
                    aInvA.getX(), aDeltaX,
268
0
                    aInvA.getY(), aDeltaY,
269
0
                    fInvZEyeA, fZDelta));
270
271
0
            return (maInverseTextureInterpolators.size() - 1);
272
0
        }
273
274
        void reset()
275
0
        {
276
0
            maColorInterpolators.clear();
277
0
            maNormalInterpolators.clear();
278
0
            maTextureInterpolators.clear();
279
0
            maInverseTextureInterpolators.clear();
280
0
        }
281
282
    public:
283
0
        InterpolatorProvider3D() {}
284
285
0
        ::std::vector< ip_triple >& getColorInterpolators() { return maColorInterpolators; }
286
0
        ::std::vector< ip_triple >& getNormalInterpolators() { return maNormalInterpolators; }
287
0
        ::std::vector< ip_double >& getTextureInterpolators() { return maTextureInterpolators; }
288
0
        ::std::vector< ip_triple >& getInverseTextureInterpolators() { return maInverseTextureInterpolators; }
289
    };
290
291
    // RasterConversionLineEntry3D for Rasterconversion of 3D PolyPolygons
292
293
    class RasterConversionLineEntry3D
294
    {
295
    private:
296
        ip_single                                   maX;
297
        ip_single                                   maZ;
298
        sal_Int32                                   mnY;
299
        sal_uInt32                                  mnCount;
300
301
        sal_uInt32                                  mnColorIndex;
302
        sal_uInt32                                  mnNormalIndex;
303
        sal_uInt32                                  mnTextureIndex;
304
        sal_uInt32                                  mnInverseTextureIndex;
305
306
    public:
307
        RasterConversionLineEntry3D(const double& rfX, const double& rfDeltaX, const double& rfZ, const double& rfDeltaZ, sal_Int32 nY, sal_uInt32 nCount)
308
0
        :   maX(rfX, rfDeltaX),
309
0
            maZ(rfZ, rfDeltaZ),
310
0
            mnY(nY),
311
0
            mnCount(nCount),
312
0
            mnColorIndex(SCANLINE_EMPTY_INDEX),
313
0
            mnNormalIndex(SCANLINE_EMPTY_INDEX),
314
0
            mnTextureIndex(SCANLINE_EMPTY_INDEX),
315
0
            mnInverseTextureIndex(SCANLINE_EMPTY_INDEX)
316
0
        {}
317
318
0
        void setColorIndex(sal_uInt32 nIndex) { mnColorIndex = nIndex; }
319
0
        void setNormalIndex(sal_uInt32 nIndex) { mnNormalIndex = nIndex; }
320
0
        void setTextureIndex(sal_uInt32 nIndex) { mnTextureIndex = nIndex; }
321
0
        void setInverseTextureIndex(sal_uInt32 nIndex) { mnInverseTextureIndex = nIndex; }
322
323
        bool operator<(const RasterConversionLineEntry3D& rComp) const
324
0
        {
325
0
            if(mnY == rComp.mnY)
326
0
            {
327
0
                return maX.getVal() < rComp.maX.getVal();
328
0
            }
329
330
0
            return mnY < rComp.mnY;
331
0
        }
332
333
        bool decrementRasterConversionLineEntry3D(sal_uInt32 nStep)
334
0
        {
335
0
            if(nStep >= mnCount)
336
0
            {
337
0
                return false;
338
0
            }
339
0
            else
340
0
            {
341
0
                mnCount -= nStep;
342
0
                return true;
343
0
            }
344
0
        }
345
346
        void incrementRasterConversionLineEntry3D(sal_uInt32 nStep, InterpolatorProvider3D& rProvider)
347
0
        {
348
0
            const double fStep(static_cast<double>(nStep));
349
0
            maX.increment(fStep);
350
0
            maZ.increment(fStep);
351
0
            mnY += nStep;
352
353
0
            if(SCANLINE_EMPTY_INDEX != mnColorIndex)
354
0
            {
355
0
                rProvider.getColorInterpolators()[mnColorIndex].increment(fStep);
356
0
            }
357
358
0
            if(SCANLINE_EMPTY_INDEX != mnNormalIndex)
359
0
            {
360
0
                rProvider.getNormalInterpolators()[mnNormalIndex].increment(fStep);
361
0
            }
362
363
0
            if(SCANLINE_EMPTY_INDEX != mnTextureIndex)
364
0
            {
365
0
                rProvider.getTextureInterpolators()[mnTextureIndex].increment(fStep);
366
0
            }
367
368
0
            if(SCANLINE_EMPTY_INDEX != mnInverseTextureIndex)
369
0
            {
370
0
                rProvider.getInverseTextureInterpolators()[mnInverseTextureIndex].increment(fStep);
371
0
            }
372
0
        }
373
374
        // data read access
375
0
        const ip_single& getX() const { return maX; }
376
0
        sal_Int32 getY() const { return mnY; }
377
0
        const ip_single& getZ() const { return maZ; }
378
0
        sal_uInt32 getColorIndex() const { return mnColorIndex; }
379
0
        sal_uInt32 getNormalIndex() const { return mnNormalIndex; }
380
0
        sal_uInt32 getTextureIndex() const { return mnTextureIndex; }
381
0
        sal_uInt32 getInverseTextureIndex() const { return mnInverseTextureIndex; }
382
    };
383
384
    // the basic RasterConverter itself. Only one method needs to be overridden. The
385
    // class itself is pure virtual
386
387
    class UNLESS_MERGELIBS(BASEGFX_DLLPUBLIC) RasterConverter3D : public InterpolatorProvider3D
388
    {
389
    private:
390
        // the line entries for an area conversion run
391
        ::std::vector< RasterConversionLineEntry3D >            maLineEntries;
392
393
        struct lineComparator
394
        {
395
            bool operator()(const RasterConversionLineEntry3D* pA, const RasterConversionLineEntry3D* pB)
396
0
            {
397
                assert(pA && pB && "lineComparator: empty pointer (!)");
398
0
                return pA->getX().getVal() < pB->getX().getVal();
399
0
            }
400
        };
401
402
        SAL_DLLPRIVATE void addArea(const B3DPolygon& rFill, const B3DHomMatrix* pViewToEye);
403
        SAL_DLLPRIVATE void addArea(const B3DPolyPolygon& rFill, const B3DHomMatrix* pViewToEye);
404
        SAL_DLLPRIVATE void addEdge(const B3DPolygon& rFill, sal_uInt32 a, sal_uInt32 b, const B3DHomMatrix* pViewToEye);
405
406
        SAL_DLLPRIVATE void rasterconvertB3DArea(sal_Int32 nStartLine, sal_Int32 nStopLine);
407
        SAL_DLLPRIVATE void rasterconvertB3DEdge(const B3DPolygon& rLine, sal_uInt32 nA, sal_uInt32 nB, sal_Int32 nStartLine, sal_Int32 nStopLine, sal_uInt16 nLineWidth);
408
409
        virtual void processLineSpan(const RasterConversionLineEntry3D& rA, const RasterConversionLineEntry3D& rB, sal_Int32 nLine, sal_uInt32 nSpanCount) = 0;
410
411
    public:
412
        RasterConverter3D();
413
        virtual ~RasterConverter3D();
414
415
        void rasterconvertB3DPolyPolygon(const B3DPolyPolygon& rFill, const B3DHomMatrix* pViewToEye, sal_Int32 nStartLine, sal_Int32 nStopLine);
416
        void rasterconvertB3DPolygon(const B3DPolygon& rLine, sal_Int32 nStartLine, sal_Int32 nStopLine, sal_uInt16 nLineWidth);
417
    };
418
} // end of namespace basegfx
419
420
/* vim:set shiftwidth=4 softtabstop=4 expandtab: */