/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: */ |