diff options
Diffstat (limited to 'include/basegfx/raster/rasterconvert3d.hxx')
-rw-r--r-- | include/basegfx/raster/rasterconvert3d.hxx | 426 |
1 files changed, 426 insertions, 0 deletions
diff --git a/include/basegfx/raster/rasterconvert3d.hxx b/include/basegfx/raster/rasterconvert3d.hxx new file mode 100644 index 000000000..59a309c86 --- /dev/null +++ b/include/basegfx/raster/rasterconvert3d.hxx @@ -0,0 +1,426 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * This file incorporates work covered by the following license notice: + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed + * with this work for additional information regarding copyright + * ownership. The ASF licenses this file to you under the Apache + * License, Version 2.0 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of + * the License at http://www.apache.org/licenses/LICENSE-2.0 . + */ + +#pragma once + +#include <config_options.h> +#include <sal/types.h> +#include <vector> + +#include <osl/diagnose.h> + +#include <basegfx/color/bcolor.hxx> +#include <basegfx/vector/b3dvector.hxx> +#include <basegfx/point/b2dpoint.hxx> +#include <basegfx/basegfxdllapi.h> + +namespace basegfx +{ + class B3DPolygon; + class B3DPolyPolygon; +} + +// interpolators for double precision + +namespace basegfx +{ + class ip_single + { + private: + double mfVal; + double mfInc; + + public: + ip_single() + : mfVal(0.0), + mfInc(0.0) + {} + + ip_single(double fVal, double fInc) + : mfVal(fVal), + mfInc(fInc) + {} + + double getVal() const { return mfVal; } + double getInc() const { return mfInc; } + + void increment(double fStep) { mfVal += fStep * mfInc; } + }; + + class ip_double + { + private: + ip_single maX; + ip_single maY; + + public: + ip_double() + : maX(), + maY() + {} + + ip_double(double fXVal, double fXInc, double fYVal, double fYInc) + : maX(fXVal, fXInc), + maY(fYVal, fYInc) + {} + + const ip_single& getX() const { return maX; } + const ip_single& getY() const { return maY; } + + void increment(double fStep) { maX.increment(fStep); maY.increment(fStep); } + }; + + class ip_triple + { + private: + ip_single maX; + ip_single maY; + ip_single maZ; + + public: + ip_triple() + : maX(), + maY(), + maZ() + {} + + ip_triple(double fXVal, double fXInc, double fYVal, double fYInc, double fZVal, double fZInc) + : maX(fXVal, fXInc), + maY(fYVal, fYInc), + maZ(fZVal, fZInc) + {} + + const ip_single& getX() const { return maX; } + const ip_single& getY() const { return maY; } + const ip_single& getZ() const { return maZ; } + + void increment(double fStep) { maX.increment(fStep); maY.increment(fStep); maZ.increment(fStep); } + }; + + // InterpolatorProvider3D to have a common source for allocating interpolators + // which may then be addressed using the index to the vectors + + #define SCANLINE_EMPTY_INDEX (0xffffffff) + + class InterpolatorProvider3D + { + private: + ::std::vector< ip_triple > maColorInterpolators; + ::std::vector< ip_triple > maNormalInterpolators; + ::std::vector< ip_double > maTextureInterpolators; + ::std::vector< ip_triple > maInverseTextureInterpolators; + + protected: + sal_uInt32 addColorInterpolator(const BColor& rA, const BColor& rB, double fInvYDelta) + { + double aDeltaRed(rB.getRed() - rA.getRed()); + + if(fTools::equalZero(aDeltaRed)) + { + aDeltaRed = 0.0; + } + else + { + aDeltaRed *= fInvYDelta; + } + + double aDeltaGreen(rB.getGreen() - rA.getGreen()); + + if(fTools::equalZero(aDeltaGreen)) + { + aDeltaGreen = 0.0; + } + else + { + aDeltaGreen *= fInvYDelta; + } + + double aDeltaBlue(rB.getBlue() - rA.getBlue()); + + if(fTools::equalZero(aDeltaBlue)) + { + aDeltaBlue = 0.0; + } + else + { + aDeltaBlue *= fInvYDelta; + } + + maColorInterpolators.push_back( + ip_triple( + rA.getRed(), aDeltaRed, + rA.getGreen(), aDeltaGreen, + rA.getBlue(), aDeltaBlue)); + + return (maColorInterpolators.size() - 1); + } + + sal_uInt32 addNormalInterpolator(const B3DVector& rA, const B3DVector& rB, double fInvYDelta) + { + double aDeltaX(rB.getX() - rA.getX()); + + if(fTools::equalZero(aDeltaX)) + { + aDeltaX = 0.0; + } + else + { + aDeltaX *= fInvYDelta; + } + + double aDeltaY(rB.getY() - rA.getY()); + + if(fTools::equalZero(aDeltaY)) + { + aDeltaY = 0.0; + } + else + { + aDeltaY *= fInvYDelta; + } + + double aDeltaZ(rB.getZ() - rA.getZ()); + + if(fTools::equalZero(aDeltaZ)) + { + aDeltaZ = 0.0; + } + else + { + aDeltaZ *= fInvYDelta; + } + + maNormalInterpolators.push_back( + ip_triple( + rA.getX(), aDeltaX, + rA.getY(), aDeltaY, + rA.getZ(), aDeltaZ)); + + return (maNormalInterpolators.size() - 1); + } + + sal_uInt32 addTextureInterpolator(const B2DPoint& rA, const B2DPoint& rB, double fInvYDelta) + { + double aDeltaX(rB.getX() - rA.getX()); + + if(fTools::equalZero(aDeltaX)) + { + aDeltaX = 0.0; + } + else + { + aDeltaX *= fInvYDelta; + } + + double aDeltaY(rB.getY() - rA.getY()); + + if(fTools::equalZero(aDeltaY)) + { + aDeltaY = 0.0; + } + else + { + aDeltaY *= fInvYDelta; + } + + maTextureInterpolators.push_back( + ip_double( + rA.getX(), aDeltaX, + rA.getY(), aDeltaY)); + + return (maTextureInterpolators.size() - 1); + } + + sal_uInt32 addInverseTextureInterpolator(const B2DPoint& rA, const B2DPoint& rB, double fZEyeA, double fZEyeB, double fInvYDelta) + { + double fZDelta(fZEyeB - fZEyeA); + const double fInvZEyeA(fTools::equalZero(fZEyeA) ? fZEyeA : 1.0 / fZEyeA); + double fInvZEyeB(fInvZEyeA); + + if(fTools::equalZero(fZDelta)) + { + fZDelta = 0.0; + } + else + { + fInvZEyeB = fTools::equalZero(fZEyeB) ? fZEyeB : 1.0 / fZEyeB; + fZDelta = (fInvZEyeB - fInvZEyeA) * fInvYDelta; + } + + const B2DPoint aInvA(rA * fInvZEyeA); + const B2DPoint aInvB(rB * fInvZEyeB); + const double aDeltaX((aInvB.getX() - aInvA.getX()) * fInvYDelta); + const double aDeltaY((aInvB.getY() - aInvA.getY()) * fInvYDelta); + + maInverseTextureInterpolators.push_back( + ip_triple( + aInvA.getX(), aDeltaX, + aInvA.getY(), aDeltaY, + fInvZEyeA, fZDelta)); + + return (maInverseTextureInterpolators.size() - 1); + } + + void reset() + { + maColorInterpolators.clear(); + maNormalInterpolators.clear(); + maTextureInterpolators.clear(); + maInverseTextureInterpolators.clear(); + } + + public: + InterpolatorProvider3D() {} + + ::std::vector< ip_triple >& getColorInterpolators() { return maColorInterpolators; } + ::std::vector< ip_triple >& getNormalInterpolators() { return maNormalInterpolators; } + ::std::vector< ip_double >& getTextureInterpolators() { return maTextureInterpolators; } + ::std::vector< ip_triple >& getInverseTextureInterpolators() { return maInverseTextureInterpolators; } + }; + + // RasterConversionLineEntry3D for Rasterconversion of 3D PolyPolygons + + class RasterConversionLineEntry3D + { + private: + ip_single maX; + ip_single maZ; + sal_Int32 mnY; + sal_uInt32 mnCount; + + sal_uInt32 mnColorIndex; + sal_uInt32 mnNormalIndex; + sal_uInt32 mnTextureIndex; + sal_uInt32 mnInverseTextureIndex; + + public: + RasterConversionLineEntry3D(const double& rfX, const double& rfDeltaX, const double& rfZ, const double& rfDeltaZ, sal_Int32 nY, sal_uInt32 nCount) + : maX(rfX, rfDeltaX), + maZ(rfZ, rfDeltaZ), + mnY(nY), + mnCount(nCount), + mnColorIndex(SCANLINE_EMPTY_INDEX), + mnNormalIndex(SCANLINE_EMPTY_INDEX), + mnTextureIndex(SCANLINE_EMPTY_INDEX), + mnInverseTextureIndex(SCANLINE_EMPTY_INDEX) + {} + + void setColorIndex(sal_uInt32 nIndex) { mnColorIndex = nIndex; } + void setNormalIndex(sal_uInt32 nIndex) { mnNormalIndex = nIndex; } + void setTextureIndex(sal_uInt32 nIndex) { mnTextureIndex = nIndex; } + void setInverseTextureIndex(sal_uInt32 nIndex) { mnInverseTextureIndex = nIndex; } + + bool operator<(const RasterConversionLineEntry3D& rComp) const + { + if(mnY == rComp.mnY) + { + return maX.getVal() < rComp.maX.getVal(); + } + + return mnY < rComp.mnY; + } + + bool decrementRasterConversionLineEntry3D(sal_uInt32 nStep) + { + if(nStep >= mnCount) + { + return false; + } + else + { + mnCount -= nStep; + return true; + } + } + + void incrementRasterConversionLineEntry3D(sal_uInt32 nStep, InterpolatorProvider3D& rProvider) + { + const double fStep(static_cast<double>(nStep)); + maX.increment(fStep); + maZ.increment(fStep); + mnY += nStep; + + if(SCANLINE_EMPTY_INDEX != mnColorIndex) + { + rProvider.getColorInterpolators()[mnColorIndex].increment(fStep); + } + + if(SCANLINE_EMPTY_INDEX != mnNormalIndex) + { + rProvider.getNormalInterpolators()[mnNormalIndex].increment(fStep); + } + + if(SCANLINE_EMPTY_INDEX != mnTextureIndex) + { + rProvider.getTextureInterpolators()[mnTextureIndex].increment(fStep); + } + + if(SCANLINE_EMPTY_INDEX != mnInverseTextureIndex) + { + rProvider.getInverseTextureInterpolators()[mnInverseTextureIndex].increment(fStep); + } + } + + // data read access + const ip_single& getX() const { return maX; } + sal_Int32 getY() const { return mnY; } + const ip_single& getZ() const { return maZ; } + sal_uInt32 getColorIndex() const { return mnColorIndex; } + sal_uInt32 getNormalIndex() const { return mnNormalIndex; } + sal_uInt32 getTextureIndex() const { return mnTextureIndex; } + sal_uInt32 getInverseTextureIndex() const { return mnInverseTextureIndex; } + }; + + // the basic RasterConverter itself. Only one method needs to be overridden. The + // class itself is pure virtual + + class UNLESS_MERGELIBS(BASEGFX_DLLPUBLIC) RasterConverter3D : public InterpolatorProvider3D + { + private: + // the line entries for an area conversion run + ::std::vector< RasterConversionLineEntry3D > maLineEntries; + + struct lineComparator + { + bool operator()(const RasterConversionLineEntry3D* pA, const RasterConversionLineEntry3D* pB) + { + OSL_ENSURE(pA && pB, "lineComparator: empty pointer (!)"); + return pA->getX().getVal() < pB->getX().getVal(); + } + }; + + void addArea(const B3DPolygon& rFill, const B3DHomMatrix* pViewToEye); + void addArea(const B3DPolyPolygon& rFill, const B3DHomMatrix* pViewToEye); + void addEdge(const B3DPolygon& rFill, sal_uInt32 a, sal_uInt32 b, const B3DHomMatrix* pViewToEye); + + void rasterconvertB3DArea(sal_Int32 nStartLine, sal_Int32 nStopLine); + void rasterconvertB3DEdge(const B3DPolygon& rLine, sal_uInt32 nA, sal_uInt32 nB, sal_Int32 nStartLine, sal_Int32 nStopLine, sal_uInt16 nLineWidth); + + virtual void processLineSpan(const RasterConversionLineEntry3D& rA, const RasterConversionLineEntry3D& rB, sal_Int32 nLine, sal_uInt32 nSpanCount) = 0; + + public: + RasterConverter3D(); + virtual ~RasterConverter3D(); + + void rasterconvertB3DPolyPolygon(const B3DPolyPolygon& rFill, const B3DHomMatrix* pViewToEye, sal_Int32 nStartLine, sal_Int32 nStopLine); + void rasterconvertB3DPolygon(const B3DPolygon& rLine, sal_Int32 nStartLine, sal_Int32 nStopLine, sal_uInt16 nLineWidth); + }; +} // end of namespace basegfx + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ |