diff options
-rw-r--r-- | drawinglayer/prj/build.lst | 23 | ||||
-rw-r--r-- | drawinglayer/prj/d.lst | 58 | ||||
-rw-r--r-- | drawinglayer/source/processor3d/baseprocessor3d.cxx | 86 | ||||
-rw-r--r-- | drawinglayer/source/processor3d/defaultprocessor3d.cxx | 1905 | ||||
-rw-r--r-- | drawinglayer/source/processor3d/makefile.mk | 54 | ||||
-rw-r--r-- | drawinglayer/source/processor3d/shadow3dextractor.cxx | 345 | ||||
-rw-r--r-- | drawinglayer/source/texture/makefile.mk | 51 | ||||
-rw-r--r-- | drawinglayer/source/texture/texture.cxx | 1090 | ||||
-rw-r--r-- | drawinglayer/util/makefile.mk | 9 |
9 files changed, 3586 insertions, 35 deletions
diff --git a/drawinglayer/prj/build.lst b/drawinglayer/prj/build.lst index ffa43f6e4b32..63d56b2b047c 100644 --- a/drawinglayer/prj/build.lst +++ b/drawinglayer/prj/build.lst @@ -1,10 +1,13 @@ -dx drawinglayer : goodies sal vcl basegfx offuh cppuhelper cppu NULL -dx drawinglayer usr1 - all dx_mkout NULL -dx drawinglayer\inc get - all dx_inc NULL -dx drawinglayer\prj get - all dx_prj NULL -dx drawinglayer\source\primitive nmake - all dx_primitive NULL -dx drawinglayer\source\primitive3d nmake - all dx_primitive3d NULL -dx drawinglayer\source\animation nmake - all dx_animation NULL -dx drawinglayer\source\geometry nmake - all dx_geometry NULL -dx drawinglayer\source\processor nmake - all dx_processor NULL -dx drawinglayer\util nmake - all dx_util dx_primitive dx_primitive3d dx_animation dx_geometry dx_processor NULL +fx drawinglayer : goodies sal vcl basegfx offuh cppuhelper cppu NULL +fx drawinglayer usr1 - all fx_mkout NULL +fx drawinglayer\inc get - all fx_inc NULL +fx drawinglayer\prj get - all fx_prj NULL +fx drawinglayer\source\primitive nmake - all fx_primitive NULL +fx drawinglayer\source\primitive3d nmake - all fx_primitive3d NULL +fx drawinglayer\source\animation nmake - all fx_animation NULL +fx drawinglayer\source\geometry nmake - all fx_geometry NULL +fx drawinglayer\source\processor nmake - all fx_processor NULL +fx drawinglayer\source\processor3d nmake - all fx_processor3d NULL +fx drawinglayer\source\attribute nmake - all fx_attribute NULL +fx drawinglayer\source\texture nmake - all fx_texture NULL +fx drawinglayer\util nmake - all fx_util fx_primitive fx_primitive3d fx_animation fx_geometry fx_processor fx_processor3d fx_attribute fx_texture NULL diff --git a/drawinglayer/prj/d.lst b/drawinglayer/prj/d.lst index 9bd83fa6bbed..f0d41821a911 100644 --- a/drawinglayer/prj/d.lst +++ b/drawinglayer/prj/d.lst @@ -10,62 +10,76 @@ mkdir: %_DEST%\inc%_EXT%\drawinglayer\primitive ..\inc\drawinglayer\primitive\animatedprimitive.hxx %_DEST%\inc%_EXT%\drawinglayer\primitive\animatedprimitive.hxx ..\inc\drawinglayer\primitive\backgroundcolorprimitive.hxx %_DEST%\inc%_EXT%\drawinglayer\primitive\backgroundcolorprimitive.hxx ..\inc\drawinglayer\primitive\bitmapprimitive.hxx %_DEST%\inc%_EXT%\drawinglayer\primitive\bitmapprimitive.hxx -..\inc\drawinglayer\primitive\fillattribute.hxx %_DEST%\inc%_EXT%\drawinglayer\primitive\fillattribute.hxx -..\inc\drawinglayer\primitive\fillbitmapattribute.hxx %_DEST%\inc%_EXT%\drawinglayer\primitive\fillbitmapattribute.hxx ..\inc\drawinglayer\primitive\fillbitmapprimitive.hxx %_DEST%\inc%_EXT%\drawinglayer\primitive\fillbitmapprimitive.hxx +..\inc\drawinglayer\primitive\embedded3dprimitive.hxx %_DEST%\inc%_EXT%\drawinglayer\primitive\embedded3dprimitive.hxx ..\inc\drawinglayer\primitive\fillgradientprimitive.hxx %_DEST%\inc%_EXT%\drawinglayer\primitive\fillgradientprimitive.hxx ..\inc\drawinglayer\primitive\fillhatchprimitive.hxx %_DEST%\inc%_EXT%\drawinglayer\primitive\fillhatchprimitive.hxx ..\inc\drawinglayer\primitive\gridprimitive.hxx %_DEST%\inc%_EXT%\drawinglayer\primitive\gridprimitive.hxx ..\inc\drawinglayer\primitive\helplineprimitive.hxx %_DEST%\inc%_EXT%\drawinglayer\primitive\helplineprimitive.hxx -..\inc\drawinglayer\primitive\vectorprimitive.hxx %_DEST%\inc%_EXT%\drawinglayer\primitive\vectorprimitive.hxx ..\inc\drawinglayer\primitive\markerprimitive.hxx %_DEST%\inc%_EXT%\drawinglayer\primitive\markerprimitive.hxx ..\inc\drawinglayer\primitive\maskprimitive.hxx %_DEST%\inc%_EXT%\drawinglayer\primitive\maskprimitive.hxx -..\inc\drawinglayer\primitive\transformprimitive.hxx %_DEST%\inc%_EXT%\drawinglayer\primitive\transformprimitive.hxx ..\inc\drawinglayer\primitive\metafileprimitive.hxx %_DEST%\inc%_EXT%\drawinglayer\primitive\metafileprimitive.hxx ..\inc\drawinglayer\primitive\modifiedcolorprimitive.hxx %_DEST%\inc%_EXT%\drawinglayer\primitive\modifiedcolorprimitive.hxx ..\inc\drawinglayer\primitive\polygonprimitive.hxx %_DEST%\inc%_EXT%\drawinglayer\primitive\polygonprimitive.hxx ..\inc\drawinglayer\primitive\polypolygonprimitive.hxx %_DEST%\inc%_EXT%\drawinglayer\primitive\polypolygonprimitive.hxx ..\inc\drawinglayer\primitive\primitive.hxx %_DEST%\inc%_EXT%\drawinglayer\primitive\primitive.hxx +..\inc\drawinglayer\primitive\primitivedefines.hxx %_DEST%\inc%_EXT%\drawinglayer\primitive\primitivedefines.hxx ..\inc\drawinglayer\primitive\sceneprimitive.hxx %_DEST%\inc%_EXT%\drawinglayer\primitive\sceneprimitive.hxx -..\inc\drawinglayer\primitive\sdrattribute.hxx %_DEST%\inc%_EXT%\drawinglayer\primitive\sdrattribute.hxx -..\inc\drawinglayer\primitive\sdrfillbitmapattribute.hxx %_DEST%\inc%_EXT%\drawinglayer\primitive\sdrfillbitmapattribute.hxx ..\inc\drawinglayer\primitive\shadowprimitive.hxx %_DEST%\inc%_EXT%\drawinglayer\primitive\shadowprimitive.hxx ..\inc\drawinglayer\primitive\simpletransparenceprimitive.hxx %_DEST%\inc%_EXT%\drawinglayer\primitive\simpletransparenceprimitive.hxx -..\inc\drawinglayer\primitive\strokearrowattribute.hxx %_DEST%\inc%_EXT%\drawinglayer\primitive\strokearrowattribute.hxx -..\inc\drawinglayer\primitive\strokeattribute.hxx %_DEST%\inc%_EXT%\drawinglayer\primitive\strokeattribute.hxx ..\inc\drawinglayer\primitive\textlayoutdevice.hxx %_DEST%\inc%_EXT%\drawinglayer\primitive\textlayoutdevice.hxx ..\inc\drawinglayer\primitive\textprimitive.hxx %_DEST%\inc%_EXT%\drawinglayer\primitive\textprimitive.hxx -..\inc\drawinglayer\primitive\texture.hxx %_DEST%\inc%_EXT%\drawinglayer\primitive\texture.hxx +..\inc\drawinglayer\primitive\transformprimitive.hxx %_DEST%\inc%_EXT%\drawinglayer\primitive\transformprimitive.hxx ..\inc\drawinglayer\primitive\transparenceprimitive.hxx %_DEST%\inc%_EXT%\drawinglayer\primitive\transparenceprimitive.hxx +..\inc\drawinglayer\primitive\vectorprimitive.hxx %_DEST%\inc%_EXT%\drawinglayer\primitive\vectorprimitive.hxx mkdir: %_DEST%\inc%_EXT%\drawinglayer\primitive3d -..\inc\drawinglayer\primitive3d\materialattribute3d.hxx %_DEST%\inc%_EXT%\drawinglayer\primitive3d\materialattribute3d.hxx -..\inc\drawinglayer\primitive3d\sdrallattribute3d.hxx %_DEST%\inc%_EXT%\drawinglayer\primitive3d\sdrallattribute3d.hxx -..\inc\drawinglayer\primitive3d\sdrattribute3d.hxx %_DEST%\inc%_EXT%\drawinglayer\primitive3d\sdrattribute3d.hxx +..\inc\drawinglayer\primitive3d\hatchtextureprimitive3d.hxx %_DEST%\inc%_EXT%\drawinglayer\primitive3d\hatchtextureprimitive3d.hxx +..\inc\drawinglayer\primitive3d\modifiedcolorprimitive3d.hxx %_DEST%\inc%_EXT%\drawinglayer\primitive3d\modifiedcolorprimitive3d.hxx ..\inc\drawinglayer\primitive3d\polygonprimitive3d.hxx %_DEST%\inc%_EXT%\drawinglayer\primitive3d\polygonprimitive3d.hxx ..\inc\drawinglayer\primitive3d\polygontubeprimitive3d.hxx %_DEST%\inc%_EXT%\drawinglayer\primitive3d\polygontubeprimitive3d.hxx ..\inc\drawinglayer\primitive3d\polypolygonprimitive3d.hxx %_DEST%\inc%_EXT%\drawinglayer\primitive3d\polypolygonprimitive3d.hxx -..\inc\drawinglayer\primitive3d\transformprimitive3d.hxx %_DEST%\inc%_EXT%\drawinglayer\primitive3d\transformprimitive3d.hxx -..\inc\drawinglayer\primitive3d\shadowprimitive3d.hxx %_DEST%\inc%_EXT%\drawinglayer\primitive3d\shadowprimitive3d.hxx -..\inc\drawinglayer\primitive3d\textureprimitive3d.hxx %_DEST%\inc%_EXT%\drawinglayer\primitive3d\textureprimitive3d.hxx -..\inc\drawinglayer\primitive3d\hatchtextureprimitive3d.hxx %_DEST%\inc%_EXT%\drawinglayer\primitive3d\hatchtextureprimitive3d.hxx +..\inc\drawinglayer\primitive3d\primitive3d.hxx %_DEST%\inc%_EXT%\drawinglayer\primitive3d\primitive3d.hxx +..\inc\drawinglayer\primitive3d\sdrcubeprimitive3d.hxx %_DEST%\inc%_EXT%\drawinglayer\primitive3d\sdrcubeprimitive3d.hxx ..\inc\drawinglayer\primitive3d\sdrdecompositiontools3d.hxx %_DEST%\inc%_EXT%\drawinglayer\primitive3d\sdrdecompositiontools3d.hxx ..\inc\drawinglayer\primitive3d\sdrextrudelathetools3d.hxx %_DEST%\inc%_EXT%\drawinglayer\primitive3d\sdrextrudelathetools3d.hxx -..\inc\drawinglayer\primitive3d\sdrprimitive3d.hxx %_DEST%\inc%_EXT%\drawinglayer\primitive3d\sdrprimitive3d.hxx -..\inc\drawinglayer\primitive3d\sdrcubeprimitive3d.hxx %_DEST%\inc%_EXT%\drawinglayer\primitive3d\sdrcubeprimitive3d.hxx ..\inc\drawinglayer\primitive3d\sdrextrudeprimitive3d.hxx %_DEST%\inc%_EXT%\drawinglayer\primitive3d\sdrextrudeprimitive3d.hxx -..\inc\drawinglayer\primitive3d\sdrsphereprimitive3d.hxx %_DEST%\inc%_EXT%\drawinglayer\primitive3d\sdrsphereprimitive3d.hxx +..\inc\drawinglayer\primitive3d\sdrlabelprimitive3d.hxx %_DEST%\inc%_EXT%\drawinglayer\primitive3d\sdrlabelprimitive3d.hxx ..\inc\drawinglayer\primitive3d\sdrlatheprimitive3d.hxx %_DEST%\inc%_EXT%\drawinglayer\primitive3d\sdrlatheprimitive3d.hxx ..\inc\drawinglayer\primitive3d\sdrpolygonprimitive3d.hxx %_DEST%\inc%_EXT%\drawinglayer\primitive3d\sdrpolygonprimitive3d.hxx +..\inc\drawinglayer\primitive3d\sdrprimitive3d.hxx %_DEST%\inc%_EXT%\drawinglayer\primitive3d\sdrprimitive3d.hxx +..\inc\drawinglayer\primitive3d\sdrsphereprimitive3d.hxx %_DEST%\inc%_EXT%\drawinglayer\primitive3d\sdrsphereprimitive3d.hxx +..\inc\drawinglayer\primitive3d\shadowprimitive3d.hxx %_DEST%\inc%_EXT%\drawinglayer\primitive3d\shadowprimitive3d.hxx +..\inc\drawinglayer\primitive3d\textureprimitive3d.hxx %_DEST%\inc%_EXT%\drawinglayer\primitive3d\textureprimitive3d.hxx +..\inc\drawinglayer\primitive3d\transformprimitive3d.hxx %_DEST%\inc%_EXT%\drawinglayer\primitive3d\transformprimitive3d.hxx +..\inc\drawinglayer\primitive3d\vectorprimitive3d.hxx %_DEST%\inc%_EXT%\drawinglayer\primitive3d\vectorprimitive3d.hxx mkdir: %_DEST%\inc%_EXT%\drawinglayer\animation ..\inc\drawinglayer\animation\animationtiming.hxx %_DEST%\inc%_EXT%\drawinglayer\animation\animationtiming.hxx mkdir: %_DEST%\inc%_EXT%\drawinglayer\geometry -..\inc\drawinglayer\geometry\viewinformation.hxx %_DEST%\inc%_EXT%\drawinglayer\geometry\viewinformation.hxx ..\inc\drawinglayer\geometry\transformation3d.hxx %_DEST%\inc%_EXT%\drawinglayer\geometry\transformation3d.hxx +..\inc\drawinglayer\geometry\viewinformation.hxx %_DEST%\inc%_EXT%\drawinglayer\geometry\viewinformation.hxx mkdir: %_DEST%\inc%_EXT%\drawinglayer\processor -..\inc\drawinglayer\processor\processor.hxx %_DEST%\inc%_EXT%\drawinglayer\processor\processor.hxx +..\inc\drawinglayer\processor\animatedextractor.hxx %_DEST%\inc%_EXT%\drawinglayer\processor\animatedextractor.hxx +..\inc\drawinglayer\processor\baseprocessor.hxx %_DEST%\inc%_EXT%\drawinglayer\processor\baseprocessor.hxx ..\inc\drawinglayer\processor\vclprocessor.hxx %_DEST%\inc%_EXT%\drawinglayer\processor\vclprocessor.hxx -..\inc\drawinglayer\processor\processor3d.hxx %_DEST%\inc%_EXT%\drawinglayer\processor\processor3d.hxx + +mkdir: %_DEST%\inc%_EXT%\drawinglayer\processor3d +..\inc\drawinglayer\processor3d\baseprocessor3d.hxx %_DEST%\inc%_EXT%\drawinglayer\processor3d\baseprocessor3d.hxx +..\inc\drawinglayer\processor3d\defaultprocessor3d.hxx %_DEST%\inc%_EXT%\drawinglayer\processor3d\defaultprocessor3d.hxx + +mkdir: %_DEST%\inc%_EXT%\drawinglayer\attribute +..\inc\drawinglayer\attribute\fillattribute.hxx %_DEST%\inc%_EXT%\drawinglayer\attribute\fillattribute.hxx +..\inc\drawinglayer\attribute\fillbitmapattribute.hxx %_DEST%\inc%_EXT%\drawinglayer\attribute\fillbitmapattribute.hxx +..\inc\drawinglayer\attribute\materialattribute3d.hxx %_DEST%\inc%_EXT%\drawinglayer\attribute\materialattribute3d.hxx +..\inc\drawinglayer\attribute\sdrallattribute3d.hxx %_DEST%\inc%_EXT%\drawinglayer\attribute\sdrallattribute3d.hxx +..\inc\drawinglayer\attribute\sdrattribute.hxx %_DEST%\inc%_EXT%\drawinglayer\attribute\sdrattribute.hxx +..\inc\drawinglayer\attribute\sdrattribute3d.hxx %_DEST%\inc%_EXT%\drawinglayer\attribute\sdrattribute3d.hxx +..\inc\drawinglayer\attribute\sdrfillbitmapattribute.hxx %_DEST%\inc%_EXT%\drawinglayer\attribute\sdrfillbitmapattribute.hxx +..\inc\drawinglayer\attribute\strokearrowattribute.hxx %_DEST%\inc%_EXT%\drawinglayer\attribute\strokearrowattribute.hxx +..\inc\drawinglayer\attribute\strokeattribute.hxx %_DEST%\inc%_EXT%\drawinglayer\attribute\strokeattribute.hxx + +mkdir: %_DEST%\inc%_EXT%\drawinglayer\texture +..\inc\drawinglayer\texture\texture.hxx %_DEST%\inc%_EXT%\drawinglayer\primitive\texture.hxx diff --git a/drawinglayer/source/processor3d/baseprocessor3d.cxx b/drawinglayer/source/processor3d/baseprocessor3d.cxx new file mode 100644 index 000000000000..01e40b43f904 --- /dev/null +++ b/drawinglayer/source/processor3d/baseprocessor3d.cxx @@ -0,0 +1,86 @@ +/************************************************************************* + * + * OpenOffice.org - a multi-platform office productivity suite + * + * $RCSfile: baseprocessor3d.cxx,v $ + * + * $Revision: 1.1 $ + * + * last change: $Author: aw $ $Date: 2006-08-09 16:57:47 $ + * + * The Contents of this file are made available subject to + * the terms of GNU Lesser General Public License Version 2.1. + * + * + * GNU Lesser General Public License Version 2.1 + * ============================================= + * Copyright 2005 by Sun Microsystems, Inc. + * 901 San Antonio Road, Palo Alto, CA 94303, USA + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License version 2.1, as published by the Free Software Foundation. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, + * MA 02111-1307 USA + * + ************************************************************************/ + +#ifndef _DRAWINGLAYER_PROCESSOR3D_BASEPROCESSOR3D_HXX +#include <drawinglayer/processor3d/baseprocessor3d.hxx> +#endif + +////////////////////////////////////////////////////////////////////////////// + +namespace drawinglayer +{ + namespace processor3d + { + baseProcessor3D::baseProcessor3D( + const geometry::viewInformation& rViewInformation, + const geometry::transformation3D& rTransformation3D) + : maViewInformation(rViewInformation), + maTransformation3D(rTransformation3D) + { + } + + baseProcessor3D::~baseProcessor3D() + { + } + } // end of namespace processor3d +} // end of namespace drawinglayer + +////////////////////////////////////////////////////////////////////////////// + +namespace drawinglayer +{ + namespace processor3d + { + collectingProcessor3D::collectingProcessor3D( + const geometry::viewInformation& rViewInformation, + const geometry::transformation3D& rTransformation3D) + : baseProcessor3D(rViewInformation, rTransformation3D) + { + } + + collectingProcessor3D::~collectingProcessor3D() + { + } + + void collectingProcessor3D::process(const primitive3d::primitiveVector3D& rSource) + { + // accept everything + maPrimitiveVector.insert(maPrimitiveVector.end(), rSource.begin(), rSource.end()); + } + } // end of namespace processor3d +} // end of namespace drawinglayer + +////////////////////////////////////////////////////////////////////////////// +// eof diff --git a/drawinglayer/source/processor3d/defaultprocessor3d.cxx b/drawinglayer/source/processor3d/defaultprocessor3d.cxx new file mode 100644 index 000000000000..4d11f2bd8fb7 --- /dev/null +++ b/drawinglayer/source/processor3d/defaultprocessor3d.cxx @@ -0,0 +1,1905 @@ +/************************************************************************* + * + * OpenOffice.org - a multi-platform office productivity suite + * + * $RCSfile: defaultprocessor3d.cxx,v $ + * + * $Revision: 1.1 $ + * + * last change: $Author: aw $ $Date: 2006-08-09 16:57:47 $ + * + * The Contents of this file are made available subject to + * the terms of GNU Lesser General Public License Version 2.1. + * + * + * GNU Lesser General Public License Version 2.1 + * ============================================= + * Copyright 2005 by Sun Microsystems, Inc. + * 901 San Antonio Road, Palo Alto, CA 94303, USA + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License version 2.1, as published by the Free Software Foundation. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, + * MA 02111-1307 USA + * + ************************************************************************/ + +#ifndef _DRAWINGLAYER_PROCESSOR3D_DEFAULTPROCESSOR3D_HXX +#include <drawinglayer/processor3d/defaultprocessor3d.hxx> +#endif + +#ifndef _SV_BMPACC_HXX +#include <vcl/bmpacc.hxx> +#endif + +#ifndef _BGFX_POLYGON_B3DPOLYGON_HXX +#include <basegfx/polygon/b3dpolygon.hxx> +#endif + +#ifndef _DRAWINGLAYER_PRIMITIVE3D_POLYGONPRIMITIVE3D_HXX +#include <drawinglayer/primitive3d/polygonprimitive3d.hxx> +#endif + +#ifndef _DRAWINGLAYER_PRIMITIVE3D_MODIFIEDCOLORPRIMITIVE3D_HXX +#include <drawinglayer/primitive3d/modifiedcolorprimitive3d.hxx> +#endif + +#ifndef _DRAWINGLAYER_PRIMITIVE3D_POLYPOLYGONPRIMITIVE_HXX +#include <drawinglayer/primitive3d/polypolygonprimitive3d.hxx> +#endif + +#ifndef _BGFX_POLYPOLYGON_B3DPOLYGONCLIPPER_HXX +#include <basegfx/polygon/b3dpolygonclipper.hxx> +#endif + +#ifndef _BGFX_RASTER_BZPIXELRASTER_HXX +#include <basegfx/raster/bzpixelraster.hxx> +#endif + +#ifndef _DRAWINGLAYER_ATTRIBUTE_SDRATTRIBUTE3D_HXX +#include <drawinglayer/attribute/sdrattribute3d.hxx> +#endif + +#ifndef _BGFX_POLYGON_B3DPOLYGONTOOLS_HXX +#include <basegfx/polygon/b3dpolygontools.hxx> +#endif + +#ifndef _BGFX_POLYPOLYGON_B3DPOLYGONTOOLS_HXX +#include <basegfx/polygon/b3dpolypolygontools.hxx> +#endif + +#ifndef _DRAWINGLAYER_PRIMITIVE3D_TEXTUREPRIMITIVE3D_HXX +#include <drawinglayer/primitive3d/textureprimitive3d.hxx> +#endif + +#ifndef _DRAWINGLAYER_PRIMITIVE3D_HATCHTEXTUREPRIMITIVE3D_HXX +#include <drawinglayer/primitive3d/hatchtextureprimitive3d.hxx> +#endif + +#ifndef _DRAWINGLAYER_PRIMITIVE3D_TRANSFORMPRIMITIVE3D_HXX +#include <drawinglayer/primitive3d/transformprimitive3d.hxx> +#endif + +////////////////////////////////////////////////////////////////////////////// + +namespace basegfx +{ + class BDInterpolator + { + protected: + double mfVal; + double mfInc; + + public: + BDInterpolator() {} + BDInterpolator(double fValA, double fValB, sal_uInt32 nCount) : mfVal(fValA), mfInc((fValB - fValA) / (double)nCount) {} + + double getVal() const { return mfVal; } + double getInc() const { return mfInc; } + void increment() { mfVal += mfInc; } + void increment(double fStep) { mfVal += fStep * mfInc; } + }; + + class BColorInterpolator + { + protected: + BColor maVal; + BColor maInc; + + public: + BColorInterpolator() {} + BColorInterpolator(const BColor& rValA, const BColor& rValB, sal_uInt32 nCount) : maVal(rValA), maInc((rValB - rValA) / (double)nCount) {} + + const BColor& getVal() const { return maVal; } + const BColor& getInc() const { return maInc; } + void increment() { maVal += maInc; } + void increment(double fStep) { maVal += fStep * maInc; } + }; + + class B3DVectorInterpolator + { + protected: + B3DVector maVal; + B3DVector maInc; + + public: + B3DVectorInterpolator() {} + B3DVectorInterpolator(const B3DVector& rValA, const B3DVector& rValB, sal_uInt32 nCount) : maVal(rValA), maInc((rValB - rValA) / (double)nCount) {} + + const B3DVector& getVal() const { return maVal; } + const B3DVector& getInc() const { return maInc; } + void increment() { maVal += maInc; } + void increment(double fStep) { maVal += fStep * maInc; } + }; + + class B2DPointInterpolator + { + protected: + B2DPoint maVal; + B2DPoint maInc; + BDInterpolator maZInv; + + public: + B2DPointInterpolator() {} + B2DPointInterpolator(const B2DPoint& rValA, const B2DPoint& rValB, double fInvZEyeA, double fInvZEyeB, sal_uInt32 nCount) + : maVal(rValA), + maInc((rValB - rValA) / (double)nCount), + maZInv(fInvZEyeA, fInvZEyeB, nCount) + {} + + const B2DPoint& getVal() const { return maVal; } + const B2DPoint& getInc() const { return maInc; } + double getZVal() const { return maZInv.getVal(); } + double getZInc() const { return maZInv.getInc(); } + void increment() { maVal += maInc; maZInv.increment(); } + void increment(double fStep) { maVal += fStep * maInc; maZInv.increment(fStep); } + }; +} // end of namespace basegfx + +////////////////////////////////////////////////////////////////////////////// + +#define SCANLINE_EMPTY_INDEX (0xffffffff) + +namespace basegfx +{ + class B3DScanlineEntry + { + protected: + sal_Int32 mnLine; + sal_uInt32 mnLineCount; + BDInterpolator maX; + BDInterpolator maZ; + + // values for normal and texture coordinate interpolation are optional, + // held simply by an index. Empty is marked by SCANLINE_EMPTY_INDEX to which it needs + // to be initialized + sal_uInt32 mnBColorIndex; + sal_uInt32 mnNormalIndex; + sal_uInt32 mnTextureCoordinateIndex; + + public: + B3DScanlineEntry() {} + + // data write access + void setLine(sal_Int32 nLine) { mnLine = nLine; } + void setLineCount(sal_uInt32 nLineCount) { mnLineCount = nLineCount; } + void setXInterpolator(const BDInterpolator& rInt) { maX = rInt; } + void setZInterpolator(const BDInterpolator& rInt) { maZ = rInt; } + void setBColorIndex(sal_uInt32 nIndex) { mnBColorIndex = nIndex; } + void setNormalIndex(sal_uInt32 nIndex) { mnNormalIndex = nIndex; } + void setTextureCoordinateIndex(sal_uInt32 nIndex) { mnTextureCoordinateIndex = nIndex; } + + // data read access + sal_Int32 getLine() const { return mnLine; } + sal_uInt32 getLineCount() const { return mnLineCount; } + const BDInterpolator& getXInterpolator() const { return maX; } + const BDInterpolator& getZInterpolator() const { return maZ; } + sal_uInt32 getBColorIndex() const {return mnBColorIndex; } + sal_uInt32 getNormalIndex() const {return mnNormalIndex; } + sal_uInt32 getTextureCoordinateIndex() const {return mnTextureCoordinateIndex; } + + bool simpleLineSortComparator(const B3DScanlineEntry& rComp) const + { + return (maX.getVal() < rComp.maX.getVal()); + } + + bool operator<(const B3DScanlineEntry& rComp) const + { + if(mnLine == rComp.mnLine) + { + return simpleLineSortComparator(rComp); + } + + return (mnLine < rComp.mnLine); + } + + bool isValid() const + { + return (0L != mnLineCount); + } + + bool decrement(sal_uInt32 nCount = 1L) + { + if(mnLineCount > nCount) + { + mnLineCount -= nCount; + return true; + } + else + { + mnLineCount = 0L; + return false; + } + } + + void increment() + { + maX.increment(); + maZ.increment(); + } + + void increment(double fStep) + { + maX.increment(fStep); + maZ.increment(fStep); + } + }; +} // end of namespace basegfx + +////////////////////////////////////////////////////////////////////////////// + +namespace basegfx +{ + class B3DPolyPolygonRasterConverter + { + protected: + ::std::vector< B3DScanlineEntry > maGlobalEntries; + ::std::vector< BColorInterpolator > maGlobalBColorInterpolators; + ::std::vector< B3DVectorInterpolator > maGlobalNormalInterpolators; + ::std::vector< B2DPointInterpolator > maGlobalTextureCoordinateInterpolators; + + // bitfield + unsigned mbAreaMode : 1; + + struct scanlineEntryComparator + { + bool operator()( const B3DScanlineEntry* pA, const B3DScanlineEntry* pB) + { + // here, Y is the same anyways (sorting a scanline), so simple compare is enough + OSL_ENSURE(pA && pB, "scanlineEntryComparator: empty pointer (!)"); + return pA->simpleLineSortComparator(*pB); + } + }; + + // add BColor interpolator, return index + sal_uInt32 addBColor(const BColor& rA, const BColor& rB, sal_uInt32 nDelta) + { + maGlobalBColorInterpolators.push_back(BColorInterpolator(rA, rB, nDelta)); + return (maGlobalBColorInterpolators.size() - 1L); + } + + // add normal interpolator, return index + sal_uInt32 addNormal(const B3DVector& rA, const B3DVector& rB, sal_uInt32 nDelta) + { + maGlobalNormalInterpolators.push_back(B3DVectorInterpolator(rA, rB, nDelta)); + return (maGlobalNormalInterpolators.size() - 1L); + } + + // add texture interpolator, return index + sal_uInt32 addTextureCoordinate(const B2DPoint& rA, const B2DPoint& rB, double fZEyeA, double fZEyeB, sal_uInt32 nDelta) + { + const double fInvZEyeA(fTools::equalZero(fZEyeA) ? fZEyeA : 1.0 / fZEyeA); + const double fInvZEyeB(fTools::equalZero(fZEyeB) ? fZEyeB : 1.0 / fZEyeB); + maGlobalTextureCoordinateInterpolators.push_back(B2DPointInterpolator(rA * fInvZEyeA, rB * fInvZEyeB, fInvZEyeA, fInvZEyeB, nDelta)); + return (maGlobalTextureCoordinateInterpolators.size() - 1L); + } + + void increment(B3DScanlineEntry& rScanEntry) + { + rScanEntry.increment(); + + const sal_uInt32 nBColor(rScanEntry.getBColorIndex()); + + if(SCANLINE_EMPTY_INDEX != nBColor) + { + maGlobalBColorInterpolators[nBColor].increment(); + } + + const sal_uInt32 nNormal(rScanEntry.getNormalIndex()); + + if(SCANLINE_EMPTY_INDEX != nNormal) + { + maGlobalNormalInterpolators[nNormal].increment(); + } + + const sal_uInt32 nTextureCoordinate(rScanEntry.getTextureCoordinateIndex()); + + if(SCANLINE_EMPTY_INDEX != nTextureCoordinate) + { + maGlobalTextureCoordinateInterpolators[nTextureCoordinate].increment(); + } + } + + void increment(B3DScanlineEntry& rScanEntry, double fStep) + { + rScanEntry.increment(fStep); + + const sal_uInt32 nBColor(rScanEntry.getBColorIndex()); + + if(SCANLINE_EMPTY_INDEX != nBColor) + { + maGlobalBColorInterpolators[nBColor].increment(fStep); + } + + const sal_uInt32 nNormal(rScanEntry.getNormalIndex()); + + if(SCANLINE_EMPTY_INDEX != nNormal) + { + maGlobalNormalInterpolators[nNormal].increment(fStep); + } + + const sal_uInt32 nTextureCoordinate(rScanEntry.getTextureCoordinateIndex()); + + if(SCANLINE_EMPTY_INDEX != nTextureCoordinate) + { + maGlobalTextureCoordinateInterpolators[nTextureCoordinate].increment(fStep); + } + } + + void addEdge(const B3DPolygon& rPolygon, const B3DHomMatrix& rInvEyeToView, sal_uInt32 nIndA, sal_uInt32 nIndB) + { + B3DPoint aPntA(rPolygon.getB3DPoint(nIndA)); + B3DPoint aPntB(rPolygon.getB3DPoint(nIndB)); + sal_Int32 nLineA((sal_Int32)(aPntA.getY())); + sal_Int32 nLineB((sal_Int32)(aPntB.getY())); + + if(nLineA == nLineB) + { + if(!mbAreaMode) + { + B3DScanlineEntry aNewEntry; + + aNewEntry.setLine(nLineA); + aNewEntry.setLineCount(0L); + aNewEntry.setXInterpolator(BDInterpolator(aPntA.getX(), aPntB.getX(), 1L)); + aNewEntry.setZInterpolator(BDInterpolator(aPntA.getZ(), aPntB.getZ(), 1L)); + aNewEntry.setBColorIndex(SCANLINE_EMPTY_INDEX); + aNewEntry.setNormalIndex(SCANLINE_EMPTY_INDEX); + aNewEntry.setTextureCoordinateIndex(SCANLINE_EMPTY_INDEX); + + maGlobalEntries.push_back(aNewEntry); + } + } + else + { + if(nLineB < nLineA) + { + ::std::swap(aPntA, aPntB); + ::std::swap(nLineA, nLineB); + ::std::swap(nIndA, nIndB); + } + + const sal_uInt32 nLineDelta(nLineB - nLineA); + B3DScanlineEntry aNewEntry; + + aNewEntry.setLine(nLineA); + aNewEntry.setLineCount(nLineDelta); + aNewEntry.setXInterpolator(BDInterpolator(aPntA.getX(), aPntB.getX(), nLineDelta)); + aNewEntry.setZInterpolator(BDInterpolator(aPntA.getZ(), aPntB.getZ(), nLineDelta)); + + const bool bColUsed(mbAreaMode && rPolygon.areBColorsUsed()); + aNewEntry.setBColorIndex(bColUsed ? addBColor(rPolygon.getBColor(nIndA), rPolygon.getBColor(nIndB), nLineDelta) : SCANLINE_EMPTY_INDEX); + + const bool bNrmUsed(mbAreaMode && rPolygon.areNormalsUsed()); + aNewEntry.setNormalIndex(bNrmUsed ? addNormal(rPolygon.getNormal(nIndA), rPolygon.getNormal(nIndB), nLineDelta) : SCANLINE_EMPTY_INDEX); + + const bool bTexUsed(mbAreaMode && rPolygon.areTextureCoordinatesUsed()); + if(bTexUsed) + { + const double fEyeA((rInvEyeToView * aPntA).getZ()); + const double fEyeB((rInvEyeToView * aPntB).getZ()); + aNewEntry.setTextureCoordinateIndex(addTextureCoordinate( + rPolygon.getTextureCoordinate(nIndA), + rPolygon.getTextureCoordinate(nIndB), + fEyeA, fEyeB, nLineDelta)); + } + else + { + aNewEntry.setTextureCoordinateIndex(SCANLINE_EMPTY_INDEX); + } + + maGlobalEntries.push_back(aNewEntry); + } + } + + // virtual rasterconverter + virtual void processSpan(const B3DScanlineEntry& rA, const B3DScanlineEntry& rB, sal_Int32 nLine, sal_uInt32 nSpanCount) = 0; + virtual void processLine(const B3DScanlineEntry& rEntry, sal_Int32 nLine) = 0; + + public: + B3DPolyPolygonRasterConverter(bool bArea) + : mbAreaMode(bArea) + { + } + + void addPolygon(const B3DPolygon& rPolygon, const B3DHomMatrix& rInvEyeToView) + { + const sal_uInt32 nPointCount(rPolygon.count()); + + if(nPointCount) + { + const sal_uInt32 nLoopCount((mbAreaMode || rPolygon.isClosed()) ? nPointCount : nPointCount - 1L); + const bool bEnoughEdges(mbAreaMode ? (nLoopCount > 2L) : (nLoopCount > 0L)); + + if(bEnoughEdges) + { + for(sal_uInt32 a(0L); a < nLoopCount; a++) + { + addEdge(rPolygon, rInvEyeToView, a, (a + 1L) % nPointCount); + } + } + } + } + + void rasterconvert(sal_Int32 nStartLine, sal_Int32 nStopLine) + { + OSL_ENSURE(nStartLine <= nStopLine, "rasterconvert: wrong start/stop line (!)"); + + if(maGlobalEntries.size()) + { + // sort global entries by YStart, xPos once + ::std::sort(maGlobalEntries.begin(), maGlobalEntries.end()); + + // local parameters + ::std::vector< B3DScanlineEntry >::iterator aCurrentGlobalEntry(maGlobalEntries.begin()); + ::std::vector< B3DScanlineEntry* > aCurrentScanLine; + ::std::vector< B3DScanlineEntry* > aNextScanLine; + ::std::vector< B3DScanlineEntry* >::iterator aScanLineEntry; + sal_Int32 nLineNumber(nStartLine); + sal_uInt32 nPairCount; + + while((nLineNumber < nStopLine) && (aCurrentScanLine.size() || aCurrentGlobalEntry != maGlobalEntries.end())) + { + // add all global entries which start at current Y to current scanline + while(aCurrentGlobalEntry != maGlobalEntries.end() && aCurrentGlobalEntry->getLine() <= nLineNumber) + { + if(aCurrentGlobalEntry->getLine() < nLineNumber) + { + // adapt to current line in nLineNumber by decrementing count incrementing accordigly + const sal_uInt32 nLineDiff(nLineNumber - aCurrentGlobalEntry->getLine()); + + if(aCurrentGlobalEntry->decrement(nLineDiff)) + { + increment(*aCurrentGlobalEntry, (double)nLineDiff); + aCurrentScanLine.push_back(&(*(aCurrentGlobalEntry))); + } + } + else + { + aCurrentScanLine.push_back(&(*(aCurrentGlobalEntry))); + } + + aCurrentGlobalEntry++; + } + + if(mbAreaMode) + { + // sort current scanline using simple comparator (only X is compared) + ::std::sort(aCurrentScanLine.begin(), aCurrentScanLine.end(), scanlineEntryComparator()); + } + + // process current scanline + aScanLineEntry = aCurrentScanLine.begin(); + aNextScanLine.clear(); + nPairCount = 0L; + + while(aScanLineEntry != aCurrentScanLine.end()) + { + B3DScanlineEntry& rPrevScanLineEntry(**aScanLineEntry++); + + if(mbAreaMode) + { + // area mode, look for 2nd span + if(aScanLineEntry != aCurrentScanLine.end()) + { + // work on span from rPrevScanLineEntry to aScanLineEntry, nLineNumber is valid + processSpan(rPrevScanLineEntry, **aScanLineEntry, nLineNumber, nPairCount++); + } + } + else + { + // work on line position rPrevScanLineEntry + processLine(rPrevScanLineEntry, nLineNumber); + } + + // do decrement counter and (evtl) increment to next line + if(rPrevScanLineEntry.decrement()) + { + increment(rPrevScanLineEntry); + aNextScanLine.push_back(&rPrevScanLineEntry); + } + } + + // copy back next scanline if count has changed + if(aNextScanLine.size() != aCurrentScanLine.size()) + { + aCurrentScanLine = aNextScanLine; + } + + // increment nLineNumber + nLineNumber++; + } + } + } + }; +} // end of namespace basegfx + +////////////////////////////////////////////////////////////////////////////// + +namespace basegfx +{ + BitmapEx getBitmapEx(const BPixelRaster& rRaster) + { + BitmapEx aRetval; + const sal_uInt32 nWidth(rRaster.getWidth()); + const sal_uInt32 nHeight(rRaster.getHeight()); + + if(nWidth && nHeight) + { + sal_uInt8 nInitAlpha(255); + Bitmap aContent(Size(nWidth, nHeight), 24); + AlphaMask aAlpha(Size(nWidth, nHeight), &nInitAlpha); + BitmapWriteAccess* pContent = aContent.AcquireWriteAccess(); + BitmapWriteAccess* pAlpha = aAlpha.AcquireWriteAccess(); + + if(pContent && pAlpha) + { + sal_uInt32 nIndex(0L); + + for(sal_uInt32 y(0L); y < nHeight; y++) + { + for(sal_uInt32 x(0L); x < nWidth; x++) + { + const BPixel& rPixel(rRaster.getBPixel(nIndex++)); + + if(rPixel.getOpacity()) + { + pContent->SetPixel(y, x, BitmapColor(rPixel.getRed(), rPixel.getGreen(), rPixel.getBlue())); + pAlpha->SetPixel(y, x, BitmapColor(255 - rPixel.getOpacity())); + } + } + } + + delete pContent; + delete pAlpha; + } + + aRetval = BitmapEx(aContent, aAlpha); + } + + return aRetval; + } +} // end of namespace basegfx + +////////////////////////////////////////////////////////////////////////////// +////////////////////////////////////////////////////////////////////////////// +////////////////////////////////////////////////////////////////////////////// + +namespace drawinglayer +{ + namespace + { + class BZPolyRaCon : public basegfx::B3DPolyPolygonRasterConverter + { + protected: + basegfx::BZPixelRaster& mrBuffer; + const attribute::materialAttribute3D& mrMaterial; + const processor3d::defaultProcessor3D& mrProcessor; + + // virtual rasterconverter + virtual void processSpan(const basegfx::B3DScanlineEntry& rA, const basegfx::B3DScanlineEntry& rB, sal_Int32 nLine, sal_uInt32 nSpanCount); + virtual void processLine(const basegfx::B3DScanlineEntry& rEntry, sal_Int32 nLine); + + public: + BZPolyRaCon( + bool bArea, + basegfx::BZPixelRaster& rBuffer, + const attribute::materialAttribute3D& rMaterial, + const processor3d::defaultProcessor3D& rProcessor) + : B3DPolyPolygonRasterConverter(bArea), + mrBuffer(rBuffer), + mrMaterial(rMaterial), + mrProcessor(rProcessor) + {} + }; + + void BZPolyRaCon::processSpan(const basegfx::B3DScanlineEntry& rA, const basegfx::B3DScanlineEntry& rB, sal_Int32 nLine, sal_uInt32 nSpanCount) + { + if(!(nSpanCount & 0x0001)) + { + if(nLine >= 0L && nLine < (sal_Int32)mrBuffer.getHeight()) + { + sal_Int32 nXA((sal_Int32)(rA.getXInterpolator().getVal())); + sal_Int32 nXB((sal_Int32)(rB.getXInterpolator().getVal())); + OSL_ENSURE(nXB >= nXA,"processSpan: positive run expected (!)"); + + if(nXB > nXA) + { + // initialize Z interpolator + const sal_uInt32 nSpanLength(nXB - nXA); + basegfx::BDInterpolator aZ(rA.getZInterpolator().getVal(), rB.getZInterpolator().getVal(), nSpanLength); + + // prepare some references to used variables + const basegfx::BColor& rColor(mrMaterial.getColor()); + const basegfx::BColor& rSpecular(mrMaterial.getSpecular()); + const basegfx::BColor& rEmission(mrMaterial.getEmission()); + const sal_uInt16 nSpecularIntensity(mrMaterial.getSpecularIntensity()); + + // get bools and init other interpolators on demand accordingly + const bool bUseTex((mrProcessor.getGeoTexSvx() || mrProcessor.getTransparenceGeoTexSvx()) && rA.getTextureCoordinateIndex() != SCANLINE_EMPTY_INDEX && rB.getTextureCoordinateIndex() != SCANLINE_EMPTY_INDEX); + const bool bUseColorTex(bUseTex && mrProcessor.getGeoTexSvx()); + const bool bNeedOthers(!bUseColorTex || (bUseColorTex && mrProcessor.getModulate())); + const bool bUseNrm(bNeedOthers && rA.getNormalIndex() != SCANLINE_EMPTY_INDEX && rB.getNormalIndex() != SCANLINE_EMPTY_INDEX); + const bool bUseCol(!bUseNrm && bNeedOthers && rA.getBColorIndex() != SCANLINE_EMPTY_INDEX && rB.getBColorIndex() != SCANLINE_EMPTY_INDEX); + const bool bModifyColor(mrProcessor.getBColorModifierStack().count()); + basegfx::B2DPointInterpolator aTex; + basegfx::B3DVectorInterpolator aNrm; + basegfx::BColorInterpolator aCol; + + if(bUseTex) + { + const basegfx::B2DPointInterpolator& rA(maGlobalTextureCoordinateInterpolators[rA.getTextureCoordinateIndex()]); + const basegfx::B2DPointInterpolator& rB(maGlobalTextureCoordinateInterpolators[rB.getTextureCoordinateIndex()]); + aTex = basegfx::B2DPointInterpolator(rA.getVal(), rB.getVal(), rA.getZVal(), rB.getZVal(), nSpanLength); + } + + if(bUseNrm) + { + aNrm = basegfx::B3DVectorInterpolator( + maGlobalNormalInterpolators[rA.getNormalIndex()].getVal(), + maGlobalNormalInterpolators[rB.getNormalIndex()].getVal(), + nSpanLength); + } + + if(bUseCol) + { + aCol = basegfx::BColorInterpolator( + maGlobalBColorInterpolators[rA.getBColorIndex()].getVal(), + maGlobalBColorInterpolators[rB.getBColorIndex()].getVal(), + nSpanLength); + } + + if(nXA < 0L) + { + const double fIncrement(-nXA); + nXA = 0L; + aZ.increment(fIncrement); + + if(bUseTex) + { + aTex.increment(fIncrement); + } + + if(bUseNrm) + { + aNrm.increment(fIncrement); + } + + if(bUseCol) + { + aCol.increment(fIncrement); + } + } + + if(nXB > (sal_Int32)mrBuffer.getWidth()) + { + nXB = mrBuffer.getWidth(); + } + + if(nXA < nXB) + { + sal_uInt32 nScanlineIndex(mrBuffer.getIndexFromXY((sal_uInt32)nXA, (sal_uInt32)nLine)); + + while(nXA < nXB) + { + // get old and new Z to see if we need to do somethng at all + sal_uInt16& rOldZ(mrBuffer.getZ(nScanlineIndex)); + const sal_uInt16 nNewZ((sal_uInt16)(aZ.getVal())); + + if(nNewZ > rOldZ) + { + // prepare color + basegfx::BColor aNewColor(rColor); + double fOpacity(1.0); + bool bOpacity(true); + + if(bUseTex) + { + // get texture coor + const basegfx::B2DPoint aTexCoor(aTex.getVal() / aTex.getZVal()); + + if(mrProcessor.getGeoTexSvx()) + { + // calc color in spot + mrProcessor.getGeoTexSvx()->modifyBColor(aTexCoor, aNewColor, fOpacity); + bOpacity = basegfx::fTools::more(fOpacity, 0.0); + } + + if(bOpacity && mrProcessor.getTransparenceGeoTexSvx()) + { + // calc opacity + mrProcessor.getTransparenceGeoTexSvx()->modifyOpacity(aTexCoor, fOpacity); + bOpacity = basegfx::fTools::more(fOpacity, 0.0); + } + } + + if(bOpacity) + { + if(mrProcessor.getGeoTexSvx()) + { + if(bUseNrm) + { + // blend texture with phong + aNewColor = mrProcessor.getSdrLightingAttribute().solveColorModel(aNrm.getVal(), aNewColor, rSpecular, rEmission, nSpecularIntensity); + } + else if(bUseCol) + { + // blend texture with gouraud + aNewColor *= aCol.getVal(); + } + else if(mrProcessor.getModulate()) + { + // blend texture with single material color + aNewColor *= rColor; + } + } + else + { + if(bUseNrm) + { + // modify color with phong + aNewColor = mrProcessor.getSdrLightingAttribute().solveColorModel(aNrm.getVal(), rColor, rSpecular, rEmission, nSpecularIntensity); + } + else if(bUseCol) + { + // modify color with gouraud + aNewColor = aCol.getVal(); + } + } + + if(bModifyColor) + { + aNewColor = mrProcessor.getBColorModifierStack().getModifiedColor(aNewColor); + } + + if(basegfx::fTools::moreOrEqual(fOpacity, 1.0)) + { + // full opacity, set z and color + rOldZ = nNewZ; + mrBuffer.getBPixel(nScanlineIndex) = basegfx::BPixel(aNewColor, 0xff); + } + else + { + basegfx::BPixel& rDest = mrBuffer.getBPixel(nScanlineIndex); + + if(rDest.getOpacity()) + { + // mix color and existing color + const double fOld(1.0 - fOpacity); + fOpacity *= 255.0; + rDest.setRed((sal_uInt8)(((double)rDest.getRed() * fOld) + (aNewColor.getRed() * fOpacity))); + rDest.setGreen((sal_uInt8)(((double)rDest.getGreen() * fOld) + (aNewColor.getGreen() * fOpacity))); + rDest.setBlue((sal_uInt8)(((double)rDest.getBlue() * fOld) + (aNewColor.getBlue() * fOpacity))); + + if((sal_uInt8)255 != rDest.getOpacity()) + { + // mix opacities by adding + double fNewOpacity(rDest.getOpacity() + fOpacity); + + if(fNewOpacity > 255.0) + { + // set full opacity + rDest.setOpacity(0xff); + } + else + { + // set new opacity which is still transparent, so set no z + rDest.setOpacity((sal_uInt8)(fNewOpacity)); + } + } + } + else + { + // set color and opacity + rDest = basegfx::BPixel(aNewColor, (sal_uInt8)(fOpacity * 255.0)); + } + } + } + } + + // increments + { + nScanlineIndex++; + nXA++; + aZ.increment(); + + if(bUseTex) + { + aTex.increment(); + } + + if(bUseNrm) + { + aNrm.increment(); + } + + if(bUseCol) + { + aCol.increment(); + } + } + } + } + } + } + } + } + + void BZPolyRaCon::processLine(const basegfx::B3DScanlineEntry& rEntry, sal_Int32 nLine) + { + if(nLine >= 0L && nLine < (sal_Int32)mrBuffer.getHeight()) + { + sal_Int32 nXA((sal_uInt32)(rEntry.getXInterpolator().getVal())); + sal_Int32 nXB((sal_uInt32)(rEntry.getXInterpolator().getVal() + rEntry.getXInterpolator().getInc())); + + if(nXA == nXB) + { + // only one position, get values and set direct + if(nXA >= 0L && nXA < (sal_Int32)mrBuffer.getWidth()) + { + const sal_uInt32 nScanlineIndex(mrBuffer.getIndexFromXY((sal_uInt32)nXA, (sal_uInt32)nLine)); + sal_uInt16& rOldZ(mrBuffer.getZ(nScanlineIndex)); + const sal_uInt16 nNewZ((sal_uInt16)(rEntry.getZInterpolator().getVal()) + 0x00ff); + + if(nNewZ > rOldZ) + { + rOldZ = nNewZ; + mrBuffer.getBPixel(nScanlineIndex) = basegfx::BPixel(mrMaterial.getColor(), 0xff); + } + } + } + else + { + const sal_uInt32 nScanlineIndexLine(mrBuffer.getIndexFromXY(0L, (sal_uInt32)nLine)); + double fZStart(rEntry.getZInterpolator().getVal()); + double fZStop(fZStart + rEntry.getZInterpolator().getInc()); + + if(nXB < nXA) + { + ::std::swap(nXB, nXA); + ::std::swap(fZStart, fZStop); + } + + const basegfx::BPixel aPixel(mrMaterial.getColor(), 0xff); + const sal_uInt32 nSpanLength(nXB - nXA); + basegfx::BDInterpolator aZ(fZStart, fZStop, nSpanLength); + + if(nXA < 0L) + { + const double fIncrement(-nXA); + nXA = 0L; + aZ.increment(fIncrement); + } + + if(nXB > (sal_Int32)mrBuffer.getWidth()) + { + nXB = mrBuffer.getWidth(); + } + + if(nXA < nXB) + { + sal_uInt32 nScanlineIndex(mrBuffer.getIndexFromXY((sal_uInt32)nXA, (sal_uInt32)nLine)); + + while(nXA < nXB) + { + sal_uInt16& rOldZ(mrBuffer.getZ(nScanlineIndex)); + const sal_uInt16 nNewZ((sal_uInt16)(aZ.getVal()) + 0x00ff); + + if(nNewZ > rOldZ) + { + rOldZ = nNewZ; + mrBuffer.getBPixel(nScanlineIndex) = aPixel; + } + + nScanlineIndex++; + nXA++; + aZ.increment(); + } + } + } + } + } + } // end of anonymous namespace +} // end of namespace drawinglayer + +////////////////////////////////////////////////////////////////////////////// +////////////////////////////////////////////////////////////////////////////// +////////////////////////////////////////////////////////////////////////////// + +namespace drawinglayer +{ + namespace texture + { + class geoTexSvxMono : public geoTexSvx + { + protected: + basegfx::BColor maSingleColor; + double mfOpacity; + + public: + geoTexSvxMono(const basegfx::BColor& rSingleColor, double fOpacity); + virtual ~geoTexSvxMono(); + + // compare operator + virtual bool operator==(const geoTexSvx& rGeoTexSvx) const; + virtual void modifyBColor(const basegfx::B2DPoint& rUV, basegfx::BColor& rBColor, double& rfOpacity) const; + virtual void modifyOpacity(const basegfx::B2DPoint& rUV, double& rfOpacity) const; + }; + + geoTexSvxMono::geoTexSvxMono(const basegfx::BColor& rSingleColor, double fOpacity) + : maSingleColor(rSingleColor), + mfOpacity(fOpacity) + { + } + + geoTexSvxMono::~geoTexSvxMono() + { + } + + bool geoTexSvxMono::operator==(const geoTexSvx& rGeoTexSvx) const + { + const geoTexSvxMono* pCompare = dynamic_cast< const geoTexSvxMono* >(&rGeoTexSvx); + return (pCompare + && maSingleColor == pCompare->maSingleColor + && mfOpacity == pCompare->mfOpacity); + } + + void geoTexSvxMono::modifyBColor(const basegfx::B2DPoint& rUV, basegfx::BColor& rBColor, double& rfOpacity) const + { + rBColor = maSingleColor; + } + + void geoTexSvxMono::modifyOpacity(const basegfx::B2DPoint& rUV, double& rfOpacity) const + { + rfOpacity = mfOpacity; + } + } // end of namespace texture +} // end of namespace drawinglayer + +////////////////////////////////////////////////////////////////////////////// + +namespace drawinglayer +{ + namespace texture + { + class geoTexSvxBitmap : public geoTexSvx + { + protected: + Bitmap maBitmap; + BitmapReadAccess* mpRead; + basegfx::B2DPoint maTopLeft; + basegfx::B2DVector maSize; + double mfMulX; + double mfMulY; + + // helpers + bool impIsValid(const basegfx::B2DPoint& rUV, sal_Int32& rX, sal_Int32& rY) const; + + public: + geoTexSvxBitmap(const Bitmap& rBitmap, const basegfx::B2DPoint& rTopLeft, const basegfx::B2DVector& rSize); + virtual ~geoTexSvxBitmap(); + virtual void modifyBColor(const basegfx::B2DPoint& rUV, basegfx::BColor& rBColor, double& rfOpacity) const; + virtual void modifyOpacity(const basegfx::B2DPoint& rUV, double& rfOpacity) const; + }; + + geoTexSvxBitmap::geoTexSvxBitmap(const Bitmap& rBitmap, const basegfx::B2DPoint& rTopLeft, const basegfx::B2DVector& rSize) + : maBitmap(rBitmap), + mpRead(0L), + maTopLeft(rTopLeft), + maSize(rSize), + mfMulX(0.0), + mfMulY(0.0) + { + mpRead = maBitmap.AcquireReadAccess(); + OSL_ENSURE(mpRead, "geoTexSvxBitmap: Got no read access to Bitmap (!)"); + mfMulX = (double)mpRead->Width() / maSize.getX(); + mfMulY = (double)mpRead->Height() / maSize.getY(); + } + + geoTexSvxBitmap::~geoTexSvxBitmap() + { + delete mpRead; + } + + bool geoTexSvxBitmap::impIsValid(const basegfx::B2DPoint& rUV, sal_Int32& rX, sal_Int32& rY) const + { + if(mpRead) + { + rX = (sal_Int32)((rUV.getX() - maTopLeft.getX()) * mfMulX); + + if(rX >= 0L && rX < mpRead->Width()) + { + rY = (sal_Int32)((rUV.getY() - maTopLeft.getY()) * mfMulY); + + return (rY >= 0L && rY < mpRead->Height()); + } + } + + return false; + } + + void geoTexSvxBitmap::modifyBColor(const basegfx::B2DPoint& rUV, basegfx::BColor& rBColor, double& rfOpacity) const + { + sal_Int32 nX, nY; + + if(impIsValid(rUV, nX, nY)) + { + rBColor = Color(mpRead->GetColor(nY, nX)).getBColor(); + } + else + { + rfOpacity = 0.0; + } + } + + void geoTexSvxBitmap::modifyOpacity(const basegfx::B2DPoint& rUV, double& rfOpacity) const + { + sal_Int32 nX, nY; + + if(impIsValid(rUV, nX, nY)) + { + rfOpacity = ((double)(0xff - Color(mpRead->GetColor(nY, nX)).GetLuminance()) * (1.0 / 255.0)); + } + else + { + rfOpacity = 0.0; + } + } + } // end of namespace texture +} // end of namespace drawinglayer + +////////////////////////////////////////////////////////////////////////////// + +namespace drawinglayer +{ + namespace texture + { + class geoTexSvxBitmapTiled : public geoTexSvxBitmap + { + protected: + // helpers + basegfx::B2DPoint impGetCorrected(const basegfx::B2DPoint& rUV) const + { + double fX(fmod(rUV.getX() - maTopLeft.getX(), maSize.getX())); + double fY(fmod(rUV.getY() - maTopLeft.getY(), maSize.getY())); + + if(fX < 0.0) + { + fX += maSize.getX(); + } + + if(fY < 0.0) + { + fY += maSize.getY(); + } + + return basegfx::B2DPoint(fX + maTopLeft.getX(), fY + maTopLeft.getY()); + } + + public: + geoTexSvxBitmapTiled(const Bitmap& rBitmap, const basegfx::B2DPoint& rTopLeft, const basegfx::B2DVector& rSize); + virtual ~geoTexSvxBitmapTiled(); + virtual void modifyBColor(const basegfx::B2DPoint& rUV, basegfx::BColor& rBColor, double& rfOpacity) const; + virtual void modifyOpacity(const basegfx::B2DPoint& rUV, double& rfOpacity) const; + }; + + geoTexSvxBitmapTiled::geoTexSvxBitmapTiled(const Bitmap& rBitmap, const basegfx::B2DPoint& rTopLeft, const basegfx::B2DVector& rSize) + : geoTexSvxBitmap(rBitmap, rTopLeft, rSize) + { + } + + geoTexSvxBitmapTiled::~geoTexSvxBitmapTiled() + { + } + + void geoTexSvxBitmapTiled::modifyBColor(const basegfx::B2DPoint& rUV, basegfx::BColor& rBColor, double& rfOpacity) const + { + if(mpRead) + { + geoTexSvxBitmap::modifyBColor(impGetCorrected(rUV), rBColor, rfOpacity); + } + } + + void geoTexSvxBitmapTiled::modifyOpacity(const basegfx::B2DPoint& rUV, double& rfOpacity) const + { + if(mpRead) + { + geoTexSvxBitmap::modifyOpacity(impGetCorrected(rUV), rfOpacity); + } + } + } // end of namespace texture +} // end of namespace drawinglayer + +////////////////////////////////////////////////////////////////////////////// + +namespace drawinglayer +{ + namespace texture + { + class geoTexSvxMultiHatch : public geoTexSvx + { + protected: + basegfx::BColor maColor; + double mfLogicPixelSize; + geoTexSvxHatch* mp0; + geoTexSvxHatch* mp1; + geoTexSvxHatch* mp2; + + // bitfield + unsigned mbFillBackground : 1; + + // helpers + bool impIsOnHatch(const basegfx::B2DPoint& rUV) const; + + public: + geoTexSvxMultiHatch(const primitive3d::hatchTexturePrimitive3D& rPrimitive, double fLogicPixelSize); + virtual ~geoTexSvxMultiHatch(); + virtual void modifyBColor(const basegfx::B2DPoint& rUV, basegfx::BColor& rBColor, double& rfOpacity) const; + virtual void modifyOpacity(const basegfx::B2DPoint& rUV, double& rfOpacity) const; + + // dada access + bool getFillBackground() const { return mbFillBackground; } + }; + + geoTexSvxMultiHatch::geoTexSvxMultiHatch(const primitive3d::hatchTexturePrimitive3D& rPrimitive, double fLogicPixelSize) + : mfLogicPixelSize(fLogicPixelSize), + mp0(0L), + mp1(0L), + mp2(0L) + { + const attribute::fillHatchAttribute& rHatch(rPrimitive.getHatch()); + const basegfx::B2DRange aOutlineRange(0.0, 0.0, rPrimitive.getTextureSize().getX(), rPrimitive.getTextureSize().getY()); + const double fAngleA(-rHatch.getAngle()); + maColor = rHatch.getColor(); + mbFillBackground = rHatch.isFillBackground(); + mp0 = new geoTexSvxHatch(aOutlineRange, rHatch.getDistance(), fAngleA); + + if(attribute::HATCHSTYLE_DOUBLE == rHatch.getStyle() || attribute::HATCHSTYLE_TRIPLE == rHatch.getStyle()) + { + mp1 = new geoTexSvxHatch(aOutlineRange, rHatch.getDistance(), fAngleA + F_PI2); + } + + if(attribute::HATCHSTYLE_TRIPLE == rHatch.getStyle()) + { + mp2 = new geoTexSvxHatch(aOutlineRange, rHatch.getDistance(), fAngleA + F_PI4); + } + } + + geoTexSvxMultiHatch::~geoTexSvxMultiHatch() + { + delete mp0; + delete mp1; + delete mp2; + } + + bool geoTexSvxMultiHatch::impIsOnHatch(const basegfx::B2DPoint& rUV) const + { + double fSmallestDistance(); + + if(mp0->getDistanceToHatch(rUV) < mfLogicPixelSize) + { + return true; + } + + if(mp1 && mp1->getDistanceToHatch(rUV) < mfLogicPixelSize) + { + return true; + } + + if(mp2 && mp2->getDistanceToHatch(rUV) < mfLogicPixelSize) + { + return true; + } + + return false; + } + + void geoTexSvxMultiHatch::modifyBColor(const basegfx::B2DPoint& rUV, basegfx::BColor& rBColor, double& rfOpacity) const + { + if(impIsOnHatch(rUV)) + { + rBColor = maColor; + } + else if(!mbFillBackground) + { + rfOpacity = 0.0; + } + } + + void geoTexSvxMultiHatch::modifyOpacity(const basegfx::B2DPoint& rUV, double& rfOpacity) const + { + if(mbFillBackground || impIsOnHatch(rUV)) + { + rfOpacity = 1.0; + } + else + { + rfOpacity = 0.0; + } + } + } // end of namespace texture +} // end of namespace drawinglayer + +////////////////////////////////////////////////////////////////////////////// +////////////////////////////////////////////////////////////////////////////// +////////////////////////////////////////////////////////////////////////////// + +namespace drawinglayer +{ + namespace processor3d + { + void defaultProcessor3D::impRender_GRX3(const primitive3d::gradientTexturePrimitive3D& rPrimitive, bool bTransparence) + { + const primitive3d::primitiveVector3D& rSubList = rPrimitive.getPrimitives(); + + if(rSubList.size()) + { + // rescue values + const bool bOldModulate(mbModulate); mbModulate = rPrimitive.getModulate(); + const bool bOldFilter(mbFilter); mbFilter = rPrimitive.getFilter(); + texture::geoTexSvx* pOldTex = (bTransparence) ? mpTransparenceGeoTexSvx : mpGeoTexSvx; + + // create texture + const attribute::fillGradientAttribute& rFillGradient = rPrimitive.getGradient(); + const basegfx::B2DRange aOutlineRange(0.0, 0.0, rPrimitive.getTextureSize().getX(), rPrimitive.getTextureSize().getY()); + const attribute::GradientStyle aGradientStyle(rFillGradient.getStyle()); + sal_uInt32 nSteps(rFillGradient.getSteps()); + const basegfx::BColor aStart(rFillGradient.getStartColor()); + const basegfx::BColor aEnd(rFillGradient.getEndColor()); + const sal_uInt32 nMaxSteps(sal_uInt32((aStart.getMaximumDistance(aEnd) * 127.5) + 0.5)); + texture::geoTexSvx* pNewTex = 0L; + + if(nMaxSteps) + { + // there IS a color distance + if(nSteps == 0L) + { + nSteps = nMaxSteps; + } + + if(nSteps < 2L) + { + nSteps = 2L; + } + + if(nSteps > nMaxSteps) + { + nSteps = nMaxSteps; + } + + switch(aGradientStyle) + { + case attribute::GRADIENTSTYLE_LINEAR: + { + pNewTex = new texture::geoTexSvxGradientLinear(aOutlineRange, aStart, aEnd, nSteps, rFillGradient.getBorder(), -rFillGradient.getAngle()); + break; + } + case attribute::GRADIENTSTYLE_AXIAL: + { + pNewTex = new texture::geoTexSvxGradientAxial(aOutlineRange, aStart, aEnd, nSteps, rFillGradient.getBorder(), -rFillGradient.getAngle()); + break; + } + case attribute::GRADIENTSTYLE_RADIAL: + { + pNewTex = new texture::geoTexSvxGradientRadial(aOutlineRange, aStart, aEnd, nSteps, rFillGradient.getBorder(), rFillGradient.getOffsetX(), rFillGradient.getOffsetY()); + break; + } + case attribute::GRADIENTSTYLE_ELLIPTICAL: + { + pNewTex = new texture::geoTexSvxGradientElliptical(aOutlineRange, aStart, aEnd, nSteps, rFillGradient.getBorder(), rFillGradient.getOffsetX(), rFillGradient.getOffsetY(), -rFillGradient.getAngle()); + break; + } + case attribute::GRADIENTSTYLE_SQUARE: + { + pNewTex = new texture::geoTexSvxGradientSquare(aOutlineRange, aStart, aEnd, nSteps, rFillGradient.getBorder(), rFillGradient.getOffsetX(), rFillGradient.getOffsetY(), -rFillGradient.getAngle()); + break; + } + case attribute::GRADIENTSTYLE_RECT: + { + pNewTex = new texture::geoTexSvxGradientRect(aOutlineRange, aStart, aEnd, nSteps, rFillGradient.getBorder(), rFillGradient.getOffsetX(), rFillGradient.getOffsetY(), -rFillGradient.getAngle()); + break; + } + } + } + else + { + // no color distance -> same color, use simple texture + pNewTex = new texture::geoTexSvxMono(aStart, 1.0 - aStart.luminance()); + } + + // set created texture + if(bTransparence) + { + mpTransparenceGeoTexSvx = pNewTex; + } + else + { + mpGeoTexSvx = pNewTex; + } + + // process sub-list + process(rSubList); + + // delete texture + delete pNewTex; + + // restore values + mbModulate = bOldModulate; + mbFilter = bOldFilter; + + if(bTransparence) + { + mpTransparenceGeoTexSvx = pOldTex; + } + else + { + mpGeoTexSvx = pOldTex; + } + } + } + + void defaultProcessor3D::impRender_HAX3(const primitive3d::hatchTexturePrimitive3D& rPrimitive) + { + const primitive3d::primitiveVector3D& rSubList = rPrimitive.getPrimitives(); + + if(rSubList.size()) + { + // rescue values + const bool bOldModulate(mbModulate); mbModulate = rPrimitive.getModulate(); + const bool bOldFilter(mbFilter); mbFilter = rPrimitive.getFilter(); + texture::geoTexSvx* pOldTex = mpGeoTexSvx; + + // calculate logic pixel size in world coordinates + const basegfx::B3DPoint aZero(maInvWorldToView * basegfx::B3DPoint(0.0, 0.0, 0.0)); + const basegfx::B3DPoint aOne(maInvWorldToView * basegfx::B3DPoint(1.0, 1.0, 1.0)); + const basegfx::B3DVector aLogicPixelSizeWorld(aOne - aZero); + double fLogicPixelSizeWorld(fabs(aLogicPixelSizeWorld.getX())); + + if(fabs(aLogicPixelSizeWorld.getY()) > fLogicPixelSizeWorld) + { + fLogicPixelSizeWorld = fabs(aLogicPixelSizeWorld.getY()); + } + + if(fabs(aLogicPixelSizeWorld.getZ()) > fLogicPixelSizeWorld) + { + fLogicPixelSizeWorld = fabs(aLogicPixelSizeWorld.getZ()); + } + + // calculate logic pixel size in texture coordinates + const double fLogicTexSizeX(fLogicPixelSizeWorld / rPrimitive.getTextureSize().getX()); + const double fLogicTexSizeY(fLogicPixelSizeWorld / rPrimitive.getTextureSize().getY()); + const double fLogicTexSize(fLogicTexSizeX > fLogicTexSizeY ? fLogicTexSizeX : fLogicTexSizeY); + + // create texture and set + texture::geoTexSvxMultiHatch* pNewTex = new texture::geoTexSvxMultiHatch(rPrimitive, fLogicTexSize); + mpGeoTexSvx = pNewTex; + + // process sub-list + process(rSubList); + + // delete texture + delete mpGeoTexSvx; + + // restore values + mbModulate = bOldModulate; + mbFilter = bOldFilter; + mpGeoTexSvx = pOldTex; + } + } + + void defaultProcessor3D::impRender_BMX3(const primitive3d::bitmapTexturePrimitive3D& rPrimitive) + { + const primitive3d::primitiveVector3D& rSubList = rPrimitive.getPrimitives(); + + if(rSubList.size()) + { + // rescue values + const bool bOldModulate(mbModulate); mbModulate = rPrimitive.getModulate(); + const bool bOldFilter(mbFilter); mbFilter = rPrimitive.getFilter(); + texture::geoTexSvx* pOldTex = mpGeoTexSvx; + + // create texture + const attribute::fillBitmapAttribute& rFillBitmapAttribute = rPrimitive.getBitmap(); + + if(rFillBitmapAttribute.getTiling()) + { + mpGeoTexSvx = new texture::geoTexSvxBitmapTiled( + rFillBitmapAttribute.getBitmap(), + rFillBitmapAttribute.getTopLeft() * rPrimitive.getTextureSize(), + rFillBitmapAttribute.getSize() * rPrimitive.getTextureSize()); + } + else + { + mpGeoTexSvx = new texture::geoTexSvxBitmap( + rFillBitmapAttribute.getBitmap(), + rFillBitmapAttribute.getTopLeft() * rPrimitive.getTextureSize(), + rFillBitmapAttribute.getSize() * rPrimitive.getTextureSize()); + } + + // process sub-list + process(rSubList); + + // delete texture + delete mpGeoTexSvx; + + // restore values + mbModulate = bOldModulate; + mbFilter = bOldFilter; + mpGeoTexSvx = pOldTex; + } + } + + void defaultProcessor3D::impRender_MCOL(const primitive3d::modifiedColorPrimitive3D& rModifiedCandidate) + { + const primitive3d::primitiveVector3D& rSubList = rModifiedCandidate.getPrimitives(); + + if(rSubList.size()) + { + maBColorModifierStack.push(rModifiedCandidate.getColorModifier()); + process(rModifiedCandidate.getPrimitives()); + maBColorModifierStack.pop(); + } + } + + void defaultProcessor3D::impRender_POH3(const primitive3d::polygonHairlinePrimitive3D& rPrimitive) + { + basegfx::B3DPolygon aHairline(rPrimitive.getB3DPolygon()); + + if(aHairline.count() && mpBZPixelRaster) + { + // hairlines need no extra data, clear it + aHairline.clearTextureCoordinates(); + aHairline.clearNormals(); + aHairline.clearBColors(); + + // transform to device coordinates (-1.0 .. 1.0) and check for visibility + aHairline.transform(maWorldToView); + const basegfx::B3DRange a3DRange(basegfx::tools::getRange(aHairline)); + const basegfx::B2DRange a2DRange(a3DRange.getMinX(), a3DRange.getMinY(), a3DRange.getMaxX(), a3DRange.getMaxY()); + + if(a2DRange.overlaps(maRasterRange)) + { + const attribute::materialAttribute3D aMaterial(rPrimitive.getBColor()); + BZPolyRaCon aNewRaCon(false, *mpBZPixelRaster, aMaterial, *this); + aNewRaCon.addPolygon(aHairline, maInvEyeToView); + aNewRaCon.rasterconvert(0L, mpBZPixelRaster->getHeight()); + } + } + } + + void defaultProcessor3D::impRender_POM3(const primitive3d::polyPolygonMaterialPrimitive3D& rPrimitive) + { + basegfx::B3DPolyPolygon aFill(rPrimitive.getB3DPolyPolygon()); + basegfx::BColor aObjectColor(rPrimitive.getMaterial().getColor()); + bool bPaintIt(aFill.count() && mpBZPixelRaster); + + if(bPaintIt) + { + // get rid of texture coordinates if there is no texture + if(aFill.areTextureCoordinatesUsed() && !mpGeoTexSvx && !mpTransparenceGeoTexSvx) + { + aFill.clearTextureCoordinates(); + } + + // transform to device coordinates (-1.0 .. 1.0) and check for visibility + aFill.transform(maWorldToView); + const basegfx::B3DRange a3DRange(basegfx::tools::getRange(aFill)); + const basegfx::B2DRange a2DRange(a3DRange.getMinX(), a3DRange.getMinY(), a3DRange.getMaxX(), a3DRange.getMaxY()); + + bPaintIt = a2DRange.overlaps(maRasterRange); + } + + // check if it shall be painted regarding hiding of normals (backface culling) + if(bPaintIt && !rPrimitive.getDoubleSided()) + { + // get plane normal of polygon in view coordinates (with ZBuffer values), + // left-handed coordinate system + const basegfx::B3DVector aPlaneNormal(aFill.getB3DPolygon(0L).getNormal()); + + if(aPlaneNormal.getZ() > 0.0) + { + bPaintIt = false; + } + } + + if(bPaintIt) + { + ::com::sun::star::drawing::ShadeMode aShadeMode(mrSdrSceneAttribute.getShadeMode()); + basegfx::B3DHomMatrix aNormalTransform(maWorldToEye); + + if(mrSdrSceneAttribute.getTwoSidedLighting()) + { + // get plane normal of polygon in view coordinates (with ZBuffer values), + // left-handed coordinate system + const basegfx::B3DVector aPlaneNormal(aFill.getB3DPolygon(0L).getNormal()); + + if(aPlaneNormal.getZ() > 0.0) + { + // mirror normals + aNormalTransform.scale(-1.0, -1.0, -1.0); + } + } + + if(::com::sun::star::drawing::ShadeMode_PHONG == aShadeMode) + { + // phong shading + if(aFill.areNormalsUsed()) + { + // transform normals to eye coor + aFill.transformNormals(aNormalTransform); + } + else + { + // fallback to gouraud when no normals available + aShadeMode = ::com::sun::star::drawing::ShadeMode_SMOOTH; + } + } + + if(::com::sun::star::drawing::ShadeMode_SMOOTH == aShadeMode) + { + // gouraud shading + if(aFill.areNormalsUsed()) + { + // transform normals to eye coor + aFill.transformNormals(aNormalTransform); + + // prepare color model parameters, evtl. use blend color + const basegfx::BColor aColor(mbModulate ? basegfx::BColor(1.0, 1.0, 1.0) : rPrimitive.getMaterial().getColor()); + const basegfx::BColor& rSpecular(rPrimitive.getMaterial().getSpecular()); + const basegfx::BColor& rEmission(rPrimitive.getMaterial().getEmission()); + const sal_uInt16 nSpecularIntensity(rPrimitive.getMaterial().getSpecularIntensity()); + + // solve color model for each normal vector, set colors at points. Clear normals. + for(sal_uInt32 a(0L); a < aFill.count(); a++) + { + basegfx::B3DPolygon aPartFill(aFill.getB3DPolygon(a)); + + for(sal_uInt32 b(0L); b < aPartFill.count(); b++) + { + // solve color model. Transform normal to eye coor + const basegfx::B3DVector aNormal(aPartFill.getNormal(b)); + const basegfx::BColor aSolvedColor(mrSdrLightingAttribute.solveColorModel(aNormal, aColor, rSpecular, rEmission, nSpecularIntensity)); + aPartFill.setBColor(b, aSolvedColor); + } + + // clear normals on this part polygon and write it back + aPartFill.clearNormals(); + aFill.setB3DPolygon(a, aPartFill); + } + } + else + { + // fallback to flat when no normals available + aShadeMode = ::com::sun::star::drawing::ShadeMode_FLAT; + } + } + + if(::com::sun::star::drawing::ShadeMode_FLAT == aShadeMode) + { + // flat shading. Clear normals and colors + aFill.clearNormals(); + aFill.clearBColors(); + + // get plane vector in eye coordinates + const basegfx::B3DVector aPlaneEyeNormal(aNormalTransform * rPrimitive.getB3DPolyPolygon().getB3DPolygon(0L).getNormal()); + + // prepare color model parameters, evtl. use blend color + const basegfx::BColor aColor(mbModulate ? basegfx::BColor(1.0, 1.0, 1.0) : rPrimitive.getMaterial().getColor()); + const basegfx::BColor& rSpecular(rPrimitive.getMaterial().getSpecular()); + const basegfx::BColor& rEmission(rPrimitive.getMaterial().getEmission()); + const sal_uInt16 nSpecularIntensity(rPrimitive.getMaterial().getSpecularIntensity()); + + // solve color model for plane vector and use that color for whole plane + aObjectColor = mrSdrLightingAttribute.solveColorModel(aPlaneEyeNormal, aColor, rSpecular, rEmission, nSpecularIntensity); + } + + if(::com::sun::star::drawing::ShadeMode_DRAFT == aShadeMode) + { + // draft, just use object color which is already set. Delete all other infos + aFill.clearNormals(); + aFill.clearBColors(); + } + } + + if(bPaintIt) + { + // draw it to ZBuffer + const attribute::materialAttribute3D aMaterial( + aObjectColor, rPrimitive.getMaterial().getSpecular(), + rPrimitive.getMaterial().getEmission(), + rPrimitive.getMaterial().getSpecularIntensity()); + BZPolyRaCon aNewRaCon(true, *mpBZPixelRaster, aMaterial, *this); + + for(sal_uInt32 a(0L); a < aFill.count(); a++) + { + aNewRaCon.addPolygon(aFill.getB3DPolygon(a), maInvEyeToView); + } + + aNewRaCon.rasterconvert(0L, mpBZPixelRaster->getHeight()); + } + } + + void defaultProcessor3D::impRender_TRN3(const primitive3d::transformPrimitive3D& rTransformCandidate) + { + // remember current transformations + basegfx::B3DHomMatrix aLastWorldToView(maWorldToView); + basegfx::B3DHomMatrix aLastWorldToEye(maWorldToEye); + basegfx::B3DHomMatrix aLastInvWorldToView(maInvWorldToView); + + // create new transformations + maWorldToView = maWorldToView * rTransformCandidate.getTransformation(); + maWorldToEye = maWorldToEye * rTransformCandidate.getTransformation(); + maInvWorldToView = maWorldToView; + maInvWorldToView.invert(); + + // let break down + process(rTransformCandidate.getPrimitives()); + + // restore transformations + maWorldToView = aLastWorldToView; + maWorldToEye = aLastWorldToEye; + maInvWorldToView = aLastInvWorldToView; + } + + void defaultProcessor3D::process(const primitive3d::primitiveVector3D& rSource) + { + for(sal_uInt32 a(0L); a < rSource.size(); a++) + { + const primitive3d::referencedPrimitive3D& rCandidate = rSource[a]; + + switch(rCandidate.getID()) + { + case CreatePrimitiveID('G', 'R', 'X', '3'): + { + // gradientTexturePrimitive3D + const primitive3d::gradientTexturePrimitive3D& rPrimitive = static_cast< const primitive3d::gradientTexturePrimitive3D& >(rCandidate.getBasePrimitive()); + impRender_GRX3(rPrimitive, false); + break; + } + + case CreatePrimitiveID('H', 'A', 'X', '3'): + { + static bool bDoHatchDecomposition(true); + + if(bDoHatchDecomposition) + { + // let break down + process(rCandidate.getBasePrimitive().getDecomposition()); + } + else + { + // hatchTexturePrimitive3D + const primitive3d::hatchTexturePrimitive3D& rPrimitive = static_cast< const primitive3d::hatchTexturePrimitive3D& >(rCandidate.getBasePrimitive()); + impRender_HAX3(rPrimitive); + } + + break; + } + + case CreatePrimitiveID('B', 'M', 'X', '3'): + { + // bitmapTexturePrimitive3D + const primitive3d::bitmapTexturePrimitive3D& rPrimitive = static_cast< const primitive3d::bitmapTexturePrimitive3D& >(rCandidate.getBasePrimitive()); + impRender_BMX3(rPrimitive); + break; + } + + case CreatePrimitiveID('T', 'R', 'X', '3'): + { + // transparenceTexturePrimitive3D + const primitive3d::transparenceTexturePrimitive3D& rPrimitive = static_cast< const primitive3d::transparenceTexturePrimitive3D& >(rCandidate.getBasePrimitive()); + + if(mbProcessTransparent) + { + impRender_GRX3(rPrimitive, true); + } + else + { + mbContainsTransparent = true; + } + + break; + } + + case CreatePrimitiveID('M', 'C', 'L', '3'): + { + // modified color group. Force output to unified color. + const primitive3d::modifiedColorPrimitive3D& rPrimitive = static_cast< const primitive3d::modifiedColorPrimitive3D& >(rCandidate.getBasePrimitive()); + impRender_MCOL(rPrimitive); + break; + } + + case CreatePrimitiveID('P', 'O', 'H', '3'): + { + // directdraw of polygonHairlinePrimitive3D + const primitive3d::polygonHairlinePrimitive3D& rPrimitive = static_cast< const primitive3d::polygonHairlinePrimitive3D& >(rCandidate.getBasePrimitive()); + + if(mbProcessTransparent == (0L != mpTransparenceGeoTexSvx)) + { + impRender_POH3(rPrimitive); + } + + break; + } + + case CreatePrimitiveID('P', 'O', 'M', '3'): + { + // directdraw of polyPolygonMaterialPrimitive3D + const primitive3d::polyPolygonMaterialPrimitive3D& rPrimitive = static_cast< const primitive3d::polyPolygonMaterialPrimitive3D& >(rCandidate.getBasePrimitive()); + + if(mbProcessTransparent == (0L != mpTransparenceGeoTexSvx)) + { + impRender_POM3(rPrimitive); + } + + break; + } + + case CreatePrimitiveID('T', 'R', 'N', '3'): + { + // transform group. + impRender_TRN3(static_cast< const primitive3d::transformPrimitive3D& >(rCandidate.getBasePrimitive())); + break; + } + + case CreatePrimitiveID('L', 'A', 'B', '3'): + { + // sdrLabelPrimitive3D. Accept, but ignore. Is handled by the scenePrimitive decompose + // method which creates 2d text objects at the 3d-projection-dependent positions. + break; + } + + default: + { + // let break down + process(rCandidate.getBasePrimitive().getDecomposition()); + break; + } + } + } + } + + void defaultProcessor3D::processNonTransparent(const primitive3d::primitiveVector3D& rSource) + { + mbProcessTransparent = false; + mbContainsTransparent = false; + process(rSource); + } + + void defaultProcessor3D::processTransparent(const primitive3d::primitiveVector3D& rSource) + { + if(mbContainsTransparent) + { + mbProcessTransparent = true; + process(rSource); + } + } + + defaultProcessor3D::defaultProcessor3D( + const geometry::viewInformation& rViewInformation, + const geometry::transformation3D& rTransformation3D, + const attribute::sdrSceneAttribute& rSdrSceneAttribute, + const attribute::sdrLightingAttribute& rsdrLightingAttribute, + double fSizeX, + double fSizeY, + const basegfx::B2DRange& rVisiblePart) + : baseProcessor3D(rViewInformation, rTransformation3D), + mrSdrSceneAttribute(rSdrSceneAttribute), + mrSdrLightingAttribute(rsdrLightingAttribute), + mpGeoTexSvx(0L), + mpTransparenceGeoTexSvx(0L), + mbModulate(false), + mbFilter(false), + mbProcessTransparent(false), + mbContainsTransparent(false) + { + // generate ViewSizes + const double fFullViewSizeX((getViewInformation().getViewTransformation() * basegfx::B2DVector(fSizeX, 0.0)).getLength()); + const double fFullViewSizeY((getViewInformation().getViewTransformation() * basegfx::B2DVector(0.0, fSizeY)).getLength()); + const double fViewSizeX(fFullViewSizeX * rVisiblePart.getWidth()); + const double fViewSizeY(fFullViewSizeY * rVisiblePart.getHeight()); + const sal_uInt32 nViewSizeX((sal_uInt32)floor(fViewSizeX)); + const sal_uInt32 nViewSizeY((sal_uInt32)floor(fViewSizeY)); + + if(nViewSizeX && nViewSizeY) + { + // create view unit buffer + mpBZPixelRaster = new basegfx::BZPixelRaster(nViewSizeX + 1L, nViewSizeY + 1L); + OSL_ENSURE(mpBZPixelRaster, "defaultProcessor3D: Could not allocate basegfx::BZPixelRaster (!)"); + + // create DeviceToView + // outcome is [-1.0 .. 1.0] in X,Y and Z. + + { + // step one: + // + // bring from [-1.0 .. 1.0] in X,Y and Z to [0.0 .. 1.0]. Also + // necessary to + // - flip Y due to screen orientation + // - flip Z due to Z-Buffer orientation from back to front + + maDeviceToView.scale(0.5, -0.5, -0.5); + maDeviceToView.translate(0.5, 0.5, 0.5); + } + + { + // step two: + // + // bring from [0.0 .. 1.0] in X,Y and Z to view cordinates. also: + // - scale Z to [0.0 .. fMaxZDepth] + const double fMaxZDepth(double(0x0000ff00)); + maDeviceToView.translate(-rVisiblePart.getMinX(), -rVisiblePart.getMinY(), 0.0); + maDeviceToView.scale(fFullViewSizeX, fFullViewSizeY, fMaxZDepth); + } + + // create world to eye transformation + maWorldToEye = getTransformation3D().getOrientation() * getTransformation3D().getTransformation(); + + // create EyeToView transformation + maWorldToView = maDeviceToView * getTransformation3D().getProjection() * maWorldToEye; + + // create inverse EyeToView transformation + maInvEyeToView = maDeviceToView * getTransformation3D().getProjection(); + maInvEyeToView.invert(); + + // create inverse WorldToView transformation + maInvWorldToView = maWorldToView; + maInvWorldToView.invert(); + + // prepare maRasterRange + maRasterRange.expand(basegfx::B2DPoint(0.0, 0.0)); + maRasterRange.expand(basegfx::B2DPoint(mpBZPixelRaster->getWidth(), mpBZPixelRaster->getHeight())); + } + } + + defaultProcessor3D::~defaultProcessor3D() + { + if(mpBZPixelRaster) + { + delete mpBZPixelRaster; + } + } + + BitmapEx defaultProcessor3D::getBitmapEx() const + { + if(mpBZPixelRaster) + { + return basegfx::getBitmapEx(*mpBZPixelRaster); + } + + return BitmapEx(); + } + } // end of namespace processor3d +} // end of namespace drawinglayer + +////////////////////////////////////////////////////////////////////////////// +// eof diff --git a/drawinglayer/source/processor3d/makefile.mk b/drawinglayer/source/processor3d/makefile.mk new file mode 100644 index 000000000000..c05046d27daa --- /dev/null +++ b/drawinglayer/source/processor3d/makefile.mk @@ -0,0 +1,54 @@ +#************************************************************************* +# +# OpenOffice.org - a multi-platform office productivity suite +# +# $RCSfile: makefile.mk,v $ +# +# $Revision: 1.1 $ +# +# last change: $Author: aw $ $Date: 2006-08-09 16:57:48 $ +# +# The Contents of this file are made available subject to +# the terms of GNU Lesser General Public License Version 2.1. +# +# +# GNU Lesser General Public License Version 2.1 +# ============================================= +# Copyright 2005 by Sun Microsystems, Inc. +# 901 San Antonio Road, Palo Alto, CA 94303, USA +# +# This library is free software; you can redistribute it and/or +# modify it under the terms of the GNU Lesser General Public +# License version 2.1, as published by the Free Software Foundation. +# +# This library is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +# Lesser General Public License for more details. +# +# You should have received a copy of the GNU Lesser General Public +# License along with this library; if not, write to the Free Software +# Foundation, Inc., 59 Temple Place, Suite 330, Boston, +# MA 02111-1307 USA +# +#************************************************************************* + +PRJ=..$/.. +PRJNAME=drawinglayer +TARGET=processor3d + +# --- Settings ---------------------------------- + +.INCLUDE : settings.mk + +# --- Files ------------------------------------- + +SLOFILES= \ + $(SLO)$/baseprocessor3d.obj \ + $(SLO)$/defaultprocessor3d.obj \ + $(SLO)$/shadow3dextractor.obj \ + $(SLO)$/label3dextractor.obj + +# --- Targets ---------------------------------- + +.INCLUDE : target.mk diff --git a/drawinglayer/source/processor3d/shadow3dextractor.cxx b/drawinglayer/source/processor3d/shadow3dextractor.cxx new file mode 100644 index 000000000000..c9a0d854061d --- /dev/null +++ b/drawinglayer/source/processor3d/shadow3dextractor.cxx @@ -0,0 +1,345 @@ +/************************************************************************* + * + * OpenOffice.org - a multi-platform office productivity suite + * + * $RCSfile: shadow3dextractor.cxx,v $ + * + * $Revision: 1.1 $ + * + * last change: $Author: aw $ $Date: 2006-08-09 16:57:48 $ + * + * The Contents of this file are made available subject to + * the terms of GNU Lesser General Public License Version 2.1. + * + * + * GNU Lesser General Public License Version 2.1 + * ============================================= + * Copyright 2005 by Sun Microsystems, Inc. + * 901 San Antonio Road, Palo Alto, CA 94303, USA + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License version 2.1, as published by the Free Software Foundation. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, + * MA 02111-1307 USA + * + ************************************************************************/ + +#ifndef _DRAWINGLAYER_PROCESSOR3D_SHADOW3DEXTRACTOR_HXX +#include <drawinglayer/processor3d/shadow3dextractor.hxx> +#endif + +#ifndef _DRAWINGLAYER_PRIMITIVE3D_SHADOWPRIMITIVE3D_HXX +#include <drawinglayer/primitive3d/shadowprimitive3d.hxx> +#endif + +#ifndef _DRAWINGLAYER_PRIMITIVE_SHADOWPRIMITIVE_HXX +#include <drawinglayer/primitive/shadowprimitive.hxx> +#endif + +#ifndef _DRAWINGLAYER_PRIMITIVE3D_TRANSFORMPRIMITIVE3D_HXX +#include <drawinglayer/primitive3d/transformprimitive3d.hxx> +#endif + +#ifndef _DRAWINGLAYER_PRIMITIVE3D_POLYGONPRIMITIVE3D_HXX +#include <drawinglayer/primitive3d/polygonprimitive3d.hxx> +#endif + +#ifndef _BGFX_POLYGON_B2DPOLYGONTOOLS_HXX +#include <basegfx/polygon/b2dpolygontools.hxx> +#endif + +#ifndef _DRAWINGLAYER_PRIMITIVE3D_POLYPOLYGONPRIMITIVE_HXX +#include <drawinglayer/primitive3d/polypolygonprimitive3d.hxx> +#endif + +#ifndef _BGFX_POLYPOLYGON_B2DPOLYGONTOOLS_HXX +#include <basegfx/polygon/b2dpolypolygontools.hxx> +#endif + +#ifndef _DRAWINGLAYER_GEOMETRY_TRANSFORMATION3D_HXX +#include <drawinglayer/geometry/transformation3d.hxx> +#endif + +#ifndef _DRAWINGLAYER_ATTRIBUTE_SDRATTRIBUTE3D_HXX +#include <drawinglayer/attribute/sdrattribute3d.hxx> +#endif + +#ifndef _DRAWINGLAYER_PRIMITIVE_SIMPLETRANSPARENCEPRIMITIVE_HXX +#include <drawinglayer/primitive/simpletransparenceprimitive.hxx> +#endif + +#ifndef _DRAWINGLAYER_PRIMITIVE_POLYGONPRIMITIVE_HXX +#include <drawinglayer/primitive/polygonprimitive.hxx> +#endif + +#ifndef _DRAWINGLAYER_PRIMITIVE_POLYPOLYGONPRIMITIVE_HXX +#include <drawinglayer/primitive/polypolygonprimitive.hxx> +#endif + +////////////////////////////////////////////////////////////////////////////// + +namespace drawinglayer +{ + namespace processor3d + { + shadow3DExtractingProcessor::shadow3DExtractingProcessor( + const geometry::viewInformation& rViewInformation, + const geometry::transformation3D& rTransformation3D, + const attribute::sdrLightingAttribute& rSdrLightingAttribute, + const primitive3d::primitiveVector3D& rPrimitiveVector, + double fShadowSlant) + : baseProcessor3D(rViewInformation, rTransformation3D), + mpTargetVector(&maPrimitiveVector), + mbShadowProjectionIsValid(false), + mbConvert(false), + mbUseProjection(false) + { + // create deviceToView projection for shadow geometry + // outcome is [-1.0 .. 1.0] in X,Y and Z. bring to [0.0 .. 1.0]. Also + // necessary to flip Y due to screen orientation + // Z is not needed, but will also be brought to [0.0 .. 1.0] + basegfx::B3DHomMatrix aDeviceToView; + aDeviceToView.scale(0.5, -0.5, 0.5); + aDeviceToView.translate(0.5, 0.5, 0.5); + + // create complete 3d transformation set for shadow stuff + maWorldToEye = getTransformation3D().getOrientation() * getTransformation3D().getTransformation(); + maEyeToView = getTransformation3D().getDeviceToView() * getTransformation3D().getProjection(); + maWorldToView = maEyeToView * maWorldToEye; + + // calculate shadow projection stuff + if(rSdrLightingAttribute.getLightVector().size()) + { + // get light normal, plane normal and sclalar from it + maLightNormal = rSdrLightingAttribute.getLightVector()[0L].getDirection(); + maLightNormal.normalize(); + maShadowPlaneNormal = basegfx::B3DVector(0.0, sin(fShadowSlant), cos(fShadowSlant)); + maShadowPlaneNormal.normalize(); + mfLightPlaneScalar = maLightNormal.scalar(maShadowPlaneNormal); + + if(basegfx::fTools::more(mfLightPlaneScalar, 0.0)) + { + // use only when scalar is > 0.0, so the light is in front of the object + basegfx::B3DRange aContained3DRange(get3DRangeFromVector(rPrimitiveVector)); + aContained3DRange.transform(maWorldToEye); + maPlanePoint.setX(maShadowPlaneNormal.getX() < 0.0 ? aContained3DRange.getMinX() : aContained3DRange.getMaxX()); + maPlanePoint.setY(maShadowPlaneNormal.getY() > 0.0 ? aContained3DRange.getMinY() : aContained3DRange.getMaxY()); + maPlanePoint.setZ(aContained3DRange.getMinZ() - (aContained3DRange.getDepth() / 8.0)); + + // set flag that shadow projection is prepared and allowed + mbShadowProjectionIsValid = true; + } + } + } + + shadow3DExtractingProcessor::~shadow3DExtractingProcessor() + { + } + + void shadow3DExtractingProcessor::process(const primitive3d::primitiveVector3D& rSource) + { + for(sal_uInt32 a(0L); a < rSource.size(); a++) + { + // get reference + const primitive3d::referencedPrimitive3D& rCandidate = rSource[a]; + + switch(rCandidate.getID()) + { + case CreatePrimitiveID('S', 'H', 'D', '3'): + { + // shadow3d object. Call recursive with content and start conversion + const primitive3d::shadowPrimitive3D& rPrimitive = static_cast< const primitive3d::shadowPrimitive3D& >(rCandidate.getBasePrimitive()); + + // set new target + primitive::primitiveVector aNewSubList; + primitive::primitiveVector* pLastTargetVector = mpTargetVector; + mpTargetVector = &aNewSubList; + + // activate convert + const bool bLastConvert(mbConvert); + mbConvert = true; + + // set projection flag + const bool bLastUseProjection(mbUseProjection); + mbUseProjection = rPrimitive.getShadow3D(); + + // process content + process(rPrimitive.getPrimitives()); + + // restore values + mbUseProjection = bLastUseProjection; + mbConvert = bLastConvert; + mpTargetVector = pLastTargetVector; + + // create 2d shadow primitive with result + primitive::shadowPrimitive* pNew = new primitive::shadowPrimitive(rPrimitive.getShadowTransform(), rPrimitive.getShadowColor(), aNewSubList); + + if(basegfx::fTools::more(rPrimitive.getShadowTransparence(), 0.0)) + { + // create simpleTransparencePrimitive, add created primitives + primitive::primitiveVector aNewTransPrimitiveVector; + aNewTransPrimitiveVector.push_back(primitive::referencedPrimitive(*pNew)); + primitive::simpleTransparencePrimitive* pNewTrans = new primitive::simpleTransparencePrimitive(rPrimitive.getShadowTransparence(), aNewTransPrimitiveVector); + mpTargetVector->push_back(primitive::referencedPrimitive(*pNewTrans)); + } + else + { + // add directly + mpTargetVector->push_back(primitive::referencedPrimitive(*pNew)); + } + + break; + } + + case CreatePrimitiveID('T', 'R', 'N', '3'): + { + // transform group. Remember current transformations + const primitive3d::transformPrimitive3D& rPrimitive = static_cast< const primitive3d::transformPrimitive3D& >(rCandidate.getBasePrimitive()); + basegfx::B3DHomMatrix aLastWorldToView(maWorldToView); + basegfx::B3DHomMatrix aLastWorldToEye(maWorldToEye); + + // create new transformations + maWorldToView = maWorldToView * rPrimitive.getTransformation(); + maWorldToEye = maWorldToEye * rPrimitive.getTransformation(); + + // let break down + process(rPrimitive.getPrimitives()); + + // restore transformations + maWorldToView = aLastWorldToView; + maWorldToEye = aLastWorldToEye; + break; + } + + case CreatePrimitiveID('P', 'O', 'H', '3'): + { + // polygonHairlinePrimitive3D + if(mbConvert) + { + const primitive3d::polygonHairlinePrimitive3D& rPrimitive = static_cast< const primitive3d::polygonHairlinePrimitive3D& >(rCandidate.getBasePrimitive()); + basegfx::B2DPolygon a2DHairline; + + if(mbUseProjection) + { + if(mbShadowProjectionIsValid) + { + a2DHairline = impDoShadowProjection(rPrimitive.getB3DPolygon()); + } + } + else + { + a2DHairline = basegfx::tools::createB2DPolygonFromB3DPolygon(rPrimitive.getB3DPolygon(), maWorldToView); + } + + if(a2DHairline.count()) + { + a2DHairline.transform(getTransformation3D().getObjectTransformation()); + primitive::polygonHairlinePrimitive* pNew = new primitive::polygonHairlinePrimitive(a2DHairline, maPrimitiveColor); + mpTargetVector->push_back(primitive::referencedPrimitive(*pNew)); + } + } + + break; + } + + case CreatePrimitiveID('P', 'O', 'M', '3'): + { + // polyPolygonMaterialPrimitive3D + if(mbConvert) + { + const primitive3d::polyPolygonMaterialPrimitive3D& rPrimitive = static_cast< const primitive3d::polyPolygonMaterialPrimitive3D& >(rCandidate.getBasePrimitive()); + basegfx::B2DPolyPolygon a2DFill; + + if(mbUseProjection) + { + if(mbShadowProjectionIsValid) + { + a2DFill = impDoShadowProjection(rPrimitive.getB3DPolyPolygon()); + } + } + else + { + a2DFill = basegfx::tools::createB2DPolyPolygonFromB3DPolyPolygon(rPrimitive.getB3DPolyPolygon(), maWorldToView); + } + + if(a2DFill.count()) + { + a2DFill.transform(getTransformation3D().getObjectTransformation()); + primitive::polyPolygonColorPrimitive* pNew = new primitive::polyPolygonColorPrimitive(a2DFill, maPrimitiveColor); + mpTargetVector->push_back(primitive::referencedPrimitive(*pNew)); + } + } + + break; + } + + case CreatePrimitiveID('L', 'A', 'B', '3'): + { + // has no 3d shadow, accept and ignore + break; + } + + default: + { + // let break down + process(rCandidate.getBasePrimitive().getDecomposition()); + break; + } + } + } + } + + basegfx::B2DPolygon shadow3DExtractingProcessor::impDoShadowProjection(const basegfx::B3DPolygon& rSource) + { + basegfx::B2DPolygon aRetval; + + for(sal_uInt32 a(0L); a < rSource.count(); a++) + { + // get point, transform to eye coordinate system + basegfx::B3DPoint aCandidate(rSource.getB3DPoint(a)); + aCandidate *= maWorldToEye; + + // we are in eye coordinates + // ray is (aCandidate + fCut * maLightNormal) + // plane is (maPlanePoint, maShadowPlaneNormal) + // maLightNormal.scalar(maShadowPlaneNormal) is already in mfLightPlaneScalar and > 0.0 + // get cut point of ray with shadow plane + const double fCut(basegfx::B3DVector(maPlanePoint - aCandidate).scalar(maShadowPlaneNormal) / mfLightPlaneScalar); + aCandidate += maLightNormal * fCut; + + // transform to view, use 2d coordinates + aCandidate *= maEyeToView; + aRetval.append(basegfx::B2DPoint(aCandidate.getX(), aCandidate.getY())); + } + + // copy closed flag + aRetval.setClosed(rSource.isClosed()); + + return aRetval; + } + + basegfx::B2DPolyPolygon shadow3DExtractingProcessor::impDoShadowProjection(const basegfx::B3DPolyPolygon& rSource) + { + basegfx::B2DPolyPolygon aRetval; + + for(sal_uInt32 a(0L); a < rSource.count(); a++) + { + aRetval.append(impDoShadowProjection(rSource.getB3DPolygon(a))); + } + + return aRetval; + } + } // end of namespace processor3d +} // end of namespace drawinglayer + +////////////////////////////////////////////////////////////////////////////// +// eof diff --git a/drawinglayer/source/texture/makefile.mk b/drawinglayer/source/texture/makefile.mk new file mode 100644 index 000000000000..877a929a8f1e --- /dev/null +++ b/drawinglayer/source/texture/makefile.mk @@ -0,0 +1,51 @@ +#************************************************************************* +# +# OpenOffice.org - a multi-platform office productivity suite +# +# $RCSfile: makefile.mk,v $ +# +# $Revision: 1.1 $ +# +# last change: $Author: aw $ $Date: 2006-08-09 16:58:20 $ +# +# The Contents of this file are made available subject to +# the terms of GNU Lesser General Public License Version 2.1. +# +# +# GNU Lesser General Public License Version 2.1 +# ============================================= +# Copyright 2005 by Sun Microsystems, Inc. +# 901 San Antonio Road, Palo Alto, CA 94303, USA +# +# This library is free software; you can redistribute it and/or +# modify it under the terms of the GNU Lesser General Public +# License version 2.1, as published by the Free Software Foundation. +# +# This library is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +# Lesser General Public License for more details. +# +# You should have received a copy of the GNU Lesser General Public +# License along with this library; if not, write to the Free Software +# Foundation, Inc., 59 Temple Place, Suite 330, Boston, +# MA 02111-1307 USA +# +#************************************************************************* + +PRJ=..$/.. +PRJNAME=drawinglayer +TARGET=texture + +# --- Settings ---------------------------------- + +.INCLUDE : settings.mk + +# --- Files ------------------------------------- + +SLOFILES= \ + $(SLO)$/texture.obj + +# --- Targets ---------------------------------- + +.INCLUDE : target.mk diff --git a/drawinglayer/source/texture/texture.cxx b/drawinglayer/source/texture/texture.cxx new file mode 100644 index 000000000000..afc6e63071ce --- /dev/null +++ b/drawinglayer/source/texture/texture.cxx @@ -0,0 +1,1090 @@ +/************************************************************************* + * + * OpenOffice.org - a multi-platform office productivity suite + * + * $RCSfile: texture.cxx,v $ + * + * $Revision: 1.1 $ + * + * last change: $Author: aw $ $Date: 2006-08-09 16:58:20 $ + * + * The Contents of this file are made available subject to + * the terms of GNU Lesser General Public License Version 2.1. + * + * + * GNU Lesser General Public License Version 2.1 + * ============================================= + * Copyright 2005 by Sun Microsystems, Inc. + * 901 San Antonio Road, Palo Alto, CA 94303, USA + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License version 2.1, as published by the Free Software Foundation. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, + * MA 02111-1307 USA + * + ************************************************************************/ + +#ifndef _DRAWINGLAYER_TEXTURE_TEXTURE_HXX +#include <drawinglayer/texture/texture.hxx> +#endif + +#ifndef _BGFX_NUMERIC_FTOOLS_HXX +#include <basegfx/numeric/ftools.hxx> +#endif + +////////////////////////////////////////////////////////////////////////////// + +namespace drawinglayer +{ + namespace texture + { + geoTexSvx::geoTexSvx() + { + } + + geoTexSvx::~geoTexSvx() + { + } + + bool geoTexSvx::operator==(const geoTexSvx& rGeoTexSvx) const + { + // default implementation says yes (no data -> no difference) + return true; + } + + void geoTexSvx::appendTransformations(::std::vector< basegfx::B2DHomMatrix >& rMatrices) + { + // default implementation does nothing + } + + void geoTexSvx::modifyBColor(const basegfx::B2DPoint& rUV, basegfx::BColor& rBColor, double& rfOpacity) const + { + // base implementation creates random color (for testing only, may also be pure virtual) + rBColor.setRed((rand() & 0x7fff) / 32767.0); + rBColor.setGreen((rand() & 0x7fff) / 32767.0); + rBColor.setBlue((rand() & 0x7fff) / 32767.0); + } + + void geoTexSvx::modifyOpacity(const basegfx::B2DPoint& rUV, double& rfOpacity) const + { + // base implementation uses inverse of luminance of solved color + basegfx::BColor aBaseColor; + modifyBColor(rUV, aBaseColor, rfOpacity); + rfOpacity = 1.0 - aBaseColor.luminance(); + } + } // end of namespace texture +} // end of namespace drawinglayer + +////////////////////////////////////////////////////////////////////////////// + +namespace drawinglayer +{ + namespace texture + { + void geoTexSvxGradient::impAppendMatrix(::std::vector< basegfx::B2DHomMatrix >& rMatrices, const basegfx::B2DRange& rRange) + { + basegfx::B2DHomMatrix aNew; + aNew.set(0, 0, rRange.getWidth()); + aNew.set(1, 1, rRange.getHeight()); + aNew.set(0, 2, rRange.getMinX()); + aNew.set(1, 2, rRange.getMinY()); + rMatrices.push_back(maTextureTransform * aNew); + } + + void geoTexSvxGradient::impAppendColorsRadial(::std::vector< basegfx::BColor >& rColors) + { + if(mnSteps) + { + rColors.push_back(maStart); + + for(sal_uInt32 a(1L); a < mnSteps - 1L; a++) + { + rColors.push_back(interpolate(maStart, maEnd, (double)a / (double)mnSteps)); + } + + rColors.push_back(maEnd); + } + } + + geoTexSvxGradient::geoTexSvxGradient(const basegfx::B2DRange& rTargetRange, const basegfx::BColor& rStart, const basegfx::BColor& rEnd, sal_uInt32 nSteps, double fBorder) + : maTargetRange(rTargetRange), + maStart(rStart), + maEnd(rEnd), + mnSteps(nSteps), + mfAspect(1.0), + mfBorder(fBorder) + { + } + + geoTexSvxGradient::~geoTexSvxGradient() + { + } + + bool geoTexSvxGradient::operator==(const geoTexSvx& rGeoTexSvx) const + { + const geoTexSvxGradient* pCompare = dynamic_cast< const geoTexSvxGradient* >(&rGeoTexSvx); + return (pCompare + && maTextureTransform == pCompare->maTextureTransform + && maTargetRange == pCompare->maTargetRange + && mnSteps == pCompare->mnSteps + && mfAspect == pCompare->mfAspect + && mfBorder == pCompare->mfBorder); + } + } // end of namespace texture +} // end of namespace drawinglayer + +////////////////////////////////////////////////////////////////////////////// + +namespace drawinglayer +{ + namespace texture + { + geoTexSvxGradientLinear::geoTexSvxGradientLinear(const basegfx::B2DRange& rTargetRange, const basegfx::BColor& rStart, const basegfx::BColor& rEnd, sal_uInt32 nSteps, double fBorder, double fAngle) + : geoTexSvxGradient(rTargetRange, rStart, rEnd, nSteps, fBorder) + { + double fTargetSizeX(maTargetRange.getWidth()); + double fTargetSizeY(maTargetRange.getHeight()); + double fTargetOffsetX(maTargetRange.getMinX()); + double fTargetOffsetY(maTargetRange.getMinY()); + + // add object expansion + if(0.0 != fAngle) + { + const double fAbsCos(fabs(cos(fAngle))); + const double fAbsSin(fabs(sin(fAngle))); + const double fNewX(fTargetSizeX * fAbsCos + fTargetSizeY * fAbsSin); + const double fNewY(fTargetSizeY * fAbsCos + fTargetSizeX * fAbsSin); + fTargetOffsetX -= (fNewX - fTargetSizeX) / 2.0; + fTargetOffsetY -= (fNewY - fTargetSizeY) / 2.0; + fTargetSizeX = fNewX; + fTargetSizeY = fNewY; + } + + // add object scale before rotate + maTextureTransform.scale(fTargetSizeX, fTargetSizeY); + + // add texture rotate after scale to keep perpendicular angles + if(0.0 != fAngle) + { + basegfx::B2DPoint aCenter(0.5, 0.5); + aCenter *= maTextureTransform; + + maTextureTransform.translate(-aCenter.getX(), -aCenter.getY()); + maTextureTransform.rotate(fAngle); + maTextureTransform.translate(aCenter.getX(), aCenter.getY()); + } + + // add object translate + maTextureTransform.translate(fTargetOffsetX, fTargetOffsetY); + + // prepare aspect for texture + mfAspect = (0.0 != fTargetSizeY) ? fTargetSizeX / fTargetSizeY : 1.0; + + // build transform from u,v to [0.0 .. 1.0]. As base, use inverse texture transform + maBackTextureTransform = maTextureTransform; + maBackTextureTransform.invert(); + maBackTextureTransform.translate(0.0, -mfBorder); + const double fSizeWithoutBorder(1.0 - mfBorder); + + if(!basegfx::fTools::equal(fSizeWithoutBorder, 0.0)) + { + maBackTextureTransform.scale(1.0, 1.0 / fSizeWithoutBorder); + } + } + + geoTexSvxGradientLinear::~geoTexSvxGradientLinear() + { + } + + void geoTexSvxGradientLinear::appendTransformations(::std::vector< basegfx::B2DHomMatrix >& rMatrices) + { + if(mnSteps) + { + const double fTop(mfBorder); + const double fStripeWidth((1.0 - fTop) / mnSteps); + + for(sal_uInt32 a(1L); a < mnSteps; a++) + { + const double fOffsetUpper(fStripeWidth * (double)a); + + // create matrix + const basegfx::B2DRange aRect(0.0, fTop + fOffsetUpper, 1.0, 1.0); + impAppendMatrix(rMatrices, aRect); + } + } + } + + void geoTexSvxGradientLinear::appendColors(::std::vector< basegfx::BColor >& rColors) + { + if(mnSteps) + { + rColors.push_back(maStart); + + for(sal_uInt32 a(1L); a < mnSteps; a++) + { + rColors.push_back(interpolate(maStart, maEnd, (double)a / (double)(mnSteps + 1L))); + } + } + } + + void geoTexSvxGradientLinear::modifyBColor(const basegfx::B2DPoint& rUV, basegfx::BColor& rBColor, double& rfOpacity) const + { + const basegfx::B2DPoint aCoor(maBackTextureTransform * rUV); + + if(basegfx::fTools::lessOrEqual(aCoor.getY(), 0.0)) + { + rBColor = maStart; + return; + } + + if(basegfx::fTools::moreOrEqual(aCoor.getY(), 1.0)) + { + rBColor = maEnd; + return; + } + + double fScaler(aCoor.getY()); + + if(mnSteps > 2L && mnSteps < 128L) + { + fScaler = floor(fScaler * (double)mnSteps) / (double)(mnSteps + 1L); + } + + rBColor = (maStart * (1.0 - fScaler)) + (maEnd * fScaler); + } + } // end of namespace texture +} // end of namespace drawinglayer + +////////////////////////////////////////////////////////////////////////////// + +namespace drawinglayer +{ + namespace texture + { + geoTexSvxGradientAxial::geoTexSvxGradientAxial(const basegfx::B2DRange& rTargetRange, const basegfx::BColor& rStart, const basegfx::BColor& rEnd, sal_uInt32 nSteps, double fBorder, double fAngle) + : geoTexSvxGradient(rTargetRange, rStart, rEnd, nSteps, fBorder) + { + double fTargetSizeX(maTargetRange.getWidth()); + double fTargetSizeY(maTargetRange.getHeight()); + double fTargetOffsetX(maTargetRange.getMinX()); + double fTargetOffsetY(maTargetRange.getMinY()); + + // add object expansion + if(0.0 != fAngle) + { + const double fAbsCos(fabs(cos(fAngle))); + const double fAbsSin(fabs(sin(fAngle))); + const double fNewX(fTargetSizeX * fAbsCos + fTargetSizeY * fAbsSin); + const double fNewY(fTargetSizeY * fAbsCos + fTargetSizeX * fAbsSin); + fTargetOffsetX -= (fNewX - fTargetSizeX) / 2.0; + fTargetOffsetY -= (fNewY - fTargetSizeY) / 2.0; + fTargetSizeX = fNewX; + fTargetSizeY = fNewY; + } + + // add object scale before rotate + maTextureTransform.scale(fTargetSizeX, fTargetSizeY); + + // add texture rotate after scale to keep perpendicular angles + if(0.0 != fAngle) + { + basegfx::B2DPoint aCenter(0.5, 0.5); + aCenter *= maTextureTransform; + + maTextureTransform.translate(-aCenter.getX(), -aCenter.getY()); + maTextureTransform.rotate(fAngle); + maTextureTransform.translate(aCenter.getX(), aCenter.getY()); + } + + // add object translate + maTextureTransform.translate(fTargetOffsetX, fTargetOffsetY); + + // prepare aspect for texture + mfAspect = (0.0 != fTargetSizeY) ? fTargetSizeX / fTargetSizeY : 1.0; + + // build transform from u,v to [0.0 .. 1.0]. As base, use inverse texture transform + maBackTextureTransform = maTextureTransform; + maBackTextureTransform.invert(); + maBackTextureTransform.translate(0.0, -0.5); + const double fSizeWithoutBorder((1.0 - mfBorder) * 0.5); + + if(!basegfx::fTools::equal(fSizeWithoutBorder, 0.0)) + { + maBackTextureTransform.scale(1.0, 1.0 / fSizeWithoutBorder); + } + + // fill internal steps for getBColor implementation + mfInternalSteps = (double)((mnSteps * 2L) - 1L); + } + + geoTexSvxGradientAxial::~geoTexSvxGradientAxial() + { + } + + void geoTexSvxGradientAxial::appendTransformations(::std::vector< basegfx::B2DHomMatrix >& rMatrices) + { + if(mnSteps) + { + const double fHalfBorder(mfBorder * 0.5); + double fTop(fHalfBorder); + double fBottom(1.0 - fHalfBorder); + const double fStripeWidth((fBottom - fTop) / ((mnSteps * 2L) - 1L)); + + for(sal_uInt32 a(1L); a < mnSteps; a++) + { + const double fOffset(fStripeWidth * (double)a); + + // create matrix + const basegfx::B2DRange aRect(0.0, fTop + fOffset, 1.0, fBottom - fOffset); + impAppendMatrix(rMatrices, aRect); + } + } + } + + void geoTexSvxGradientAxial::appendColors(::std::vector< basegfx::BColor >& rColors) + { + if(mnSteps) + { + rColors.push_back(maEnd); + + for(sal_uInt32 a(1L); a < mnSteps; a++) + { + rColors.push_back(interpolate(maEnd, maStart, (double)a / (double)mnSteps)); + } + } + } + + void geoTexSvxGradientAxial::modifyBColor(const basegfx::B2DPoint& rUV, basegfx::BColor& rBColor, double& rfOpacity) const + { + const basegfx::B2DPoint aCoor(maBackTextureTransform * rUV); + const double fAbsY(fabs(aCoor.getY())); + + if(basegfx::fTools::moreOrEqual(fAbsY, 1.0)) + { + rBColor = maEnd; + return; + } + + double fScaler(fAbsY); + + if(mnSteps > 2L && mnSteps < 128L) + { + fScaler = floor(((fScaler * mfInternalSteps) + 1.0) / 2.0) / (double)(mnSteps - 1L); + } + + rBColor = (maStart * (1.0 - fScaler)) + (maEnd * fScaler); + } + } // end of namespace texture +} // end of namespace drawinglayer + +////////////////////////////////////////////////////////////////////////////// + +namespace drawinglayer +{ + namespace texture + { + geoTexSvxGradientRadial::geoTexSvxGradientRadial(const basegfx::B2DRange& rTargetRange, const basegfx::BColor& rStart, const basegfx::BColor& rEnd, sal_uInt32 nSteps, double fBorder, double fOffsetX, double fOffsetY) + : geoTexSvxGradient(rTargetRange, rStart, rEnd, nSteps, fBorder) + { + double fTargetSizeX(maTargetRange.getWidth()); + double fTargetSizeY(maTargetRange.getHeight()); + double fTargetOffsetX(maTargetRange.getMinX()); + double fTargetOffsetY(maTargetRange.getMinY()); + + // add object expansion + const double fOriginalDiag(sqrt((fTargetSizeX * fTargetSizeX) + (fTargetSizeY * fTargetSizeY))); + fTargetOffsetX -= (fOriginalDiag - fTargetSizeX) / 2.0; + fTargetOffsetY -= (fOriginalDiag - fTargetSizeY) / 2.0; + fTargetSizeX = fOriginalDiag; + fTargetSizeY = fOriginalDiag; + + // add object scale before rotate + maTextureTransform.scale(fTargetSizeX, fTargetSizeY); + + // add defined offsets after rotation + if(0.5 != fOffsetX || 0.5 != fOffsetY) + { + // use original target size + fTargetOffsetX += (fOffsetX - 0.5) * maTargetRange.getWidth(); + fTargetOffsetY += (fOffsetY - 0.5) * maTargetRange.getHeight(); + } + + // add object translate + maTextureTransform.translate(fTargetOffsetX, fTargetOffsetY); + + // prepare aspect for texture + mfAspect = (0.0 != fTargetSizeY) ? fTargetSizeX / fTargetSizeY : 1.0; + + // build transform from u,v to [0.0 .. 1.0]. As base, use inverse texture transform + maBackTextureTransform = maTextureTransform; + maBackTextureTransform.invert(); + maBackTextureTransform.translate(-0.5, -0.5); + const double fHalfBorder((1.0 - mfBorder) * 0.5); + + if(!basegfx::fTools::equal(fHalfBorder, 0.0)) + { + const double fFactor(1.0 / fHalfBorder); + maBackTextureTransform.scale(fFactor, fFactor); + } + } + + geoTexSvxGradientRadial::~geoTexSvxGradientRadial() + { + } + + void geoTexSvxGradientRadial::appendTransformations(::std::vector< basegfx::B2DHomMatrix >& rMatrices) + { + if(mnSteps) + { + const double fHalfBorder((1.0 - mfBorder) * 0.5); + double fLeft(0.5 - fHalfBorder); + double fTop(0.5 - fHalfBorder); + double fRight(0.5 + fHalfBorder); + double fBottom(0.5 + fHalfBorder); + double fIncrementX, fIncrementY; + + if(mfAspect > 1.0) + { + fIncrementY = (fBottom - fTop) / (double)(mnSteps * 2L); + fIncrementX = fIncrementY / mfAspect; + } + else + { + fIncrementX = (fRight - fLeft) / (double)(mnSteps * 2L); + fIncrementY = fIncrementX * mfAspect; + } + + for(sal_uInt32 a(1L); a < mnSteps; a++) + { + // next step + fLeft += fIncrementX; + fRight -= fIncrementX; + fTop += fIncrementY; + fBottom -= fIncrementY; + + // create matrix + const basegfx::B2DRange aRect(fLeft, fTop, fRight, fBottom); + impAppendMatrix(rMatrices, aRect); + } + } + } + + void geoTexSvxGradientRadial::appendColors(::std::vector< basegfx::BColor >& rColors) + { + impAppendColorsRadial(rColors); + } + + void geoTexSvxGradientRadial::modifyBColor(const basegfx::B2DPoint& rUV, basegfx::BColor& rBColor, double& rfOpacity) const + { + const basegfx::B2DPoint aCoor(maBackTextureTransform * rUV); + const double fDist(aCoor.getX() * aCoor.getX() + aCoor.getY() * aCoor.getY()); + + if(basegfx::fTools::moreOrEqual(fDist, 1.0)) + { + rBColor = maStart; + return; + } + + double fScaler(1.0 - sqrt(fDist)); + + if(mnSteps > 2L && mnSteps < 128L) + { + fScaler = floor(fScaler * (double)mnSteps) / (double)(mnSteps - 1L); + } + + rBColor = (maStart * (1.0 - fScaler)) + (maEnd * fScaler); + } + } // end of namespace texture +} // end of namespace drawinglayer + +////////////////////////////////////////////////////////////////////////////// + +namespace drawinglayer +{ + namespace texture + { + geoTexSvxGradientElliptical::geoTexSvxGradientElliptical(const basegfx::B2DRange& rTargetRange, const basegfx::BColor& rStart, const basegfx::BColor& rEnd, sal_uInt32 nSteps, double fBorder, double fOffsetX, double fOffsetY, double fAngle) + : geoTexSvxGradient(rTargetRange, rStart, rEnd, nSteps, fBorder) + { + double fTargetSizeX(maTargetRange.getWidth()); + double fTargetSizeY(maTargetRange.getHeight()); + double fTargetOffsetX(maTargetRange.getMinX()); + double fTargetOffsetY(maTargetRange.getMinY()); + + // add object expansion + fTargetOffsetX -= (0.4142 / 2.0 ) * fTargetSizeX; + fTargetOffsetY -= (0.4142 / 2.0 ) * fTargetSizeY; + fTargetSizeX = 1.4142 * fTargetSizeX; + fTargetSizeY = 1.4142 * fTargetSizeY; + + // add object scale before rotate + maTextureTransform.scale(fTargetSizeX, fTargetSizeY); + + // add texture rotate after scale to keep perpendicular angles + if(0.0 != fAngle) + { + basegfx::B2DPoint aCenter(0.5, 0.5); + aCenter *= maTextureTransform; + + maTextureTransform.translate(-aCenter.getX(), -aCenter.getY()); + maTextureTransform.rotate(fAngle); + maTextureTransform.translate(aCenter.getX(), aCenter.getY()); + } + + // add defined offsets after rotation + if(0.5 != fOffsetX || 0.5 != fOffsetY) + { + // use original target size + fTargetOffsetX += (fOffsetX - 0.5) * maTargetRange.getWidth(); + fTargetOffsetY += (fOffsetY - 0.5) * maTargetRange.getHeight(); + } + + // add object translate + maTextureTransform.translate(fTargetOffsetX, fTargetOffsetY); + + // prepare aspect for texture + mfAspect = (0.0 != fTargetSizeY) ? fTargetSizeX / fTargetSizeY : 1.0; + + // build transform from u,v to [0.0 .. 1.0]. As base, use inverse texture transform + maBackTextureTransform = maTextureTransform; + maBackTextureTransform.invert(); + maBackTextureTransform.translate(-0.5, -0.5); + const double fHalfBorder((1.0 - mfBorder) * 0.5); + + if(!basegfx::fTools::equal(fHalfBorder, 0.0)) + { + const double fFactor(1.0 / fHalfBorder); + maBackTextureTransform.scale(fFactor, fFactor); + } + } + + geoTexSvxGradientElliptical::~geoTexSvxGradientElliptical() + { + } + + void geoTexSvxGradientElliptical::appendTransformations(::std::vector< basegfx::B2DHomMatrix >& rMatrices) + { + if(mnSteps) + { + const double fHalfBorder((1.0 - mfBorder) * 0.5); + double fLeft(0.5 - fHalfBorder); + double fTop(0.5 - fHalfBorder); + double fRight(0.5 + fHalfBorder); + double fBottom(0.5 + fHalfBorder); + double fIncrementX, fIncrementY; + + if(mfAspect > 1.0) + { + fIncrementY = (fBottom - fTop) / (double)(mnSteps * 2L); + fIncrementX = fIncrementY / mfAspect; + } + else + { + fIncrementX = (fRight - fLeft) / (double)(mnSteps * 2L); + fIncrementY = fIncrementX * mfAspect; + } + + for(sal_uInt32 a(1L); a < mnSteps; a++) + { + // next step + fLeft += fIncrementX; + fRight -= fIncrementX; + fTop += fIncrementY; + fBottom -= fIncrementY; + + // create matrix + const basegfx::B2DRange aRect(fLeft, fTop, fRight, fBottom); + impAppendMatrix(rMatrices, aRect); + } + } + } + + void geoTexSvxGradientElliptical::appendColors(::std::vector< basegfx::BColor >& rColors) + { + impAppendColorsRadial(rColors); + } + + void geoTexSvxGradientElliptical::modifyBColor(const basegfx::B2DPoint& rUV, basegfx::BColor& rBColor, double& rfOpacity) const + { + const basegfx::B2DPoint aCoor(maBackTextureTransform * rUV); + const double fDist(aCoor.getX() * aCoor.getX() + aCoor.getY() * aCoor.getY()); + + if(basegfx::fTools::moreOrEqual(fDist, 1.0)) + { + rBColor = maStart; + return; + } + + double fScaler(1.0 - sqrt(fDist)); + + if(mnSteps > 2L && mnSteps < 128L) + { + fScaler = floor(fScaler * (double)mnSteps) / (double)(mnSteps - 1L); + } + + rBColor = (maStart * (1.0 - fScaler)) + (maEnd * fScaler); + } + } // end of namespace texture +} // end of namespace drawinglayer + +////////////////////////////////////////////////////////////////////////////// + +namespace drawinglayer +{ + namespace texture + { + geoTexSvxGradientSquare::geoTexSvxGradientSquare(const basegfx::B2DRange& rTargetRange, const basegfx::BColor& rStart, const basegfx::BColor& rEnd, sal_uInt32 nSteps, double fBorder, double fOffsetX, double fOffsetY, double fAngle) + : geoTexSvxGradient(rTargetRange, rStart, rEnd, nSteps, fBorder) + { + double fTargetSizeX(maTargetRange.getWidth()); + double fTargetSizeY(maTargetRange.getHeight()); + double fTargetOffsetX(maTargetRange.getMinX()); + double fTargetOffsetY(maTargetRange.getMinY()); + + // add object expansion + if(0.0 != fAngle) + { + const double fAbsCos(fabs(cos(fAngle))); + const double fAbsSin(fabs(sin(fAngle))); + const double fNewX(fTargetSizeX * fAbsCos + fTargetSizeY * fAbsSin); + const double fNewY(fTargetSizeY * fAbsCos + fTargetSizeX * fAbsSin); + fTargetOffsetX -= (fNewX - fTargetSizeX) / 2.0; + fTargetOffsetY -= (fNewY - fTargetSizeY) / 2.0; + fTargetSizeX = fNewX; + fTargetSizeY = fNewY; + } + + // add object scale before rotate + maTextureTransform.scale(fTargetSizeX, fTargetSizeY); + + // add texture rotate after scale to keep perpendicular angles + if(0.0 != fAngle) + { + basegfx::B2DPoint aCenter(0.5, 0.5); + aCenter *= maTextureTransform; + + maTextureTransform.translate(-aCenter.getX(), -aCenter.getY()); + maTextureTransform.rotate(fAngle); + maTextureTransform.translate(aCenter.getX(), aCenter.getY()); + } + + // add defined offsets after rotation + if(0.5 != fOffsetX || 0.5 != fOffsetY) + { + // use scaled target size + fTargetOffsetX += (fOffsetX - 0.5) * fTargetSizeX; + fTargetOffsetY += (fOffsetY - 0.5) * fTargetSizeY; + } + + // add object translate + maTextureTransform.translate(fTargetOffsetX, fTargetOffsetY); + + // prepare aspect for texture + mfAspect = (0.0 != fTargetSizeY) ? fTargetSizeX / fTargetSizeY : 1.0; + + // build transform from u,v to [0.0 .. 1.0]. As base, use inverse texture transform + maBackTextureTransform = maTextureTransform; + maBackTextureTransform.invert(); + maBackTextureTransform.translate(-0.5, -0.5); + const double fHalfBorder((1.0 - mfBorder) * 0.5); + + if(!basegfx::fTools::equal(fHalfBorder, 0.0)) + { + const double fFactor(1.0 / fHalfBorder); + maBackTextureTransform.scale(fFactor, fFactor); + } + } + + geoTexSvxGradientSquare::~geoTexSvxGradientSquare() + { + } + + void geoTexSvxGradientSquare::appendTransformations(::std::vector< basegfx::B2DHomMatrix >& rMatrices) + { + if(mnSteps) + { + const double fHalfBorder((1.0 - mfBorder) * 0.5); + double fLeft(0.5 - fHalfBorder); + double fTop(0.5 - fHalfBorder); + double fRight(0.5 + fHalfBorder); + double fBottom(0.5 + fHalfBorder); + double fIncrementX, fIncrementY; + + if(mfAspect > 1.0) + { + const double fWidth(fRight - fLeft); + const double fHalfAspectExpansion(((mfAspect - 1.0) * 0.5) * fWidth); + fTop -= fHalfAspectExpansion; + fBottom += fHalfAspectExpansion; + fIncrementX = fWidth / (double)(mnSteps * 2L); + fIncrementY = fIncrementX * mfAspect; + } + else + { + const double fHeight(fBottom - fTop); + const double fHalfAspectExpansion((((1.0 / mfAspect) - 1.0) * 0.5) * fHeight); + fLeft -= fHalfAspectExpansion; + fRight += fHalfAspectExpansion; + fIncrementY = fHeight / (double)(mnSteps * 2L); + fIncrementX = fIncrementY / mfAspect; + } + + for(sal_uInt32 a(1L); a < mnSteps; a++) + { + // next step + fLeft += fIncrementX; + fRight -= fIncrementX; + fTop += fIncrementY; + fBottom -= fIncrementY; + + // create matrix + const basegfx::B2DRange aRect(fLeft, fTop, fRight, fBottom); + impAppendMatrix(rMatrices, aRect); + } + } + } + + void geoTexSvxGradientSquare::appendColors(::std::vector< basegfx::BColor >& rColors) + { + impAppendColorsRadial(rColors); + } + + void geoTexSvxGradientSquare::modifyBColor(const basegfx::B2DPoint& rUV, basegfx::BColor& rBColor, double& rfOpacity) const + { + const basegfx::B2DPoint aCoor(maBackTextureTransform * rUV); + const double fAbsX(fabs(aCoor.getX())); + const double fAbsY(fabs(aCoor.getY())); + + if(basegfx::fTools::moreOrEqual(fAbsX, 1.0) || basegfx::fTools::moreOrEqual(fAbsY, 1.0)) + { + rBColor = maStart; + return; + } + + double fScaler(1.0 - (fAbsX > fAbsY ? fAbsX : fAbsY)); + + if(mnSteps > 2L && mnSteps < 128L) + { + fScaler = floor(fScaler * (double)mnSteps) / (double)(mnSteps - 1L); + } + + rBColor = (maStart * (1.0 - fScaler)) + (maEnd * fScaler); + } + } // end of namespace texture +} // end of namespace drawinglayer + +////////////////////////////////////////////////////////////////////////////// + +namespace drawinglayer +{ + namespace texture + { + geoTexSvxGradientRect::geoTexSvxGradientRect(const basegfx::B2DRange& rTargetRange, const basegfx::BColor& rStart, const basegfx::BColor& rEnd, sal_uInt32 nSteps, double fBorder, double fOffsetX, double fOffsetY, double fAngle) + : geoTexSvxGradient(rTargetRange, rStart, rEnd, nSteps, fBorder) + { + double fTargetSizeX(maTargetRange.getWidth()); + double fTargetSizeY(maTargetRange.getHeight()); + double fTargetOffsetX(maTargetRange.getMinX()); + double fTargetOffsetY(maTargetRange.getMinY()); + + // add object expansion + if(0.0 != fAngle) + { + const double fAbsCos(fabs(cos(fAngle))); + const double fAbsSin(fabs(sin(fAngle))); + const double fNewX(fTargetSizeX * fAbsCos + fTargetSizeY * fAbsSin); + const double fNewY(fTargetSizeY * fAbsCos + fTargetSizeX * fAbsSin); + fTargetOffsetX -= (fNewX - fTargetSizeX) / 2.0; + fTargetOffsetY -= (fNewY - fTargetSizeY) / 2.0; + fTargetSizeX = fNewX; + fTargetSizeY = fNewY; + } + + // add object scale before rotate + maTextureTransform.scale(fTargetSizeX, fTargetSizeY); + + // add texture rotate after scale to keep perpendicular angles + if(0.0 != fAngle) + { + basegfx::B2DPoint aCenter(0.5, 0.5); + aCenter *= maTextureTransform; + + maTextureTransform.translate(-aCenter.getX(), -aCenter.getY()); + maTextureTransform.rotate(fAngle); + maTextureTransform.translate(aCenter.getX(), aCenter.getY()); + } + + // add defined offsets after rotation + if(0.5 != fOffsetX || 0.5 != fOffsetY) + { + // use scaled target size + fTargetOffsetX += (fOffsetX - 0.5) * fTargetSizeX; + fTargetOffsetY += (fOffsetY - 0.5) * fTargetSizeY; + } + + // add object translate + maTextureTransform.translate(fTargetOffsetX, fTargetOffsetY); + + // prepare aspect for texture + mfAspect = (0.0 != fTargetSizeY) ? fTargetSizeX / fTargetSizeY : 1.0; + + // build transform from u,v to [0.0 .. 1.0]. As base, use inverse texture transform + maBackTextureTransform = maTextureTransform; + maBackTextureTransform.invert(); + maBackTextureTransform.translate(-0.5, -0.5); + const double fHalfBorder((1.0 - mfBorder) * 0.5); + + if(!basegfx::fTools::equal(fHalfBorder, 0.0)) + { + const double fFactor(1.0 / fHalfBorder); + maBackTextureTransform.scale(fFactor, fFactor); + } + } + + geoTexSvxGradientRect::~geoTexSvxGradientRect() + { + } + + void geoTexSvxGradientRect::appendTransformations(::std::vector< basegfx::B2DHomMatrix >& rMatrices) + { + if(mnSteps) + { + const double fHalfBorder((1.0 - mfBorder) * 0.5); + double fLeft(0.5 - fHalfBorder); + double fTop(0.5 - fHalfBorder); + double fRight(0.5 + fHalfBorder); + double fBottom(0.5 + fHalfBorder); + double fIncrementX, fIncrementY; + + if(mfAspect > 1.0) + { + fIncrementY = (fBottom - fTop) / (double)(mnSteps * 2L); + fIncrementX = fIncrementY / mfAspect; + } + else + { + fIncrementX = (fRight - fLeft) / (double)(mnSteps * 2L); + fIncrementY = fIncrementX * mfAspect; + } + + for(sal_uInt32 a(1L); a < mnSteps; a++) + { + // next step + fLeft += fIncrementX; + fRight -= fIncrementX; + fTop += fIncrementY; + fBottom -= fIncrementY; + + // create matrix + const basegfx::B2DRange aRect(fLeft, fTop, fRight, fBottom); + impAppendMatrix(rMatrices, aRect); + } + } + } + + void geoTexSvxGradientRect::appendColors(::std::vector< basegfx::BColor >& rColors) + { + impAppendColorsRadial(rColors); + } + + void geoTexSvxGradientRect::modifyBColor(const basegfx::B2DPoint& rUV, basegfx::BColor& rBColor, double& rfOpacity) const + { + const basegfx::B2DPoint aCoor(maBackTextureTransform * rUV); + const double fAbsX(fabs(aCoor.getX())); + const double fAbsY(fabs(aCoor.getY())); + + if(basegfx::fTools::moreOrEqual(fAbsX, 1.0) || basegfx::fTools::moreOrEqual(fAbsY, 1.0)) + { + rBColor = maStart; + return; + } + + double fScaler(1.0 - (fAbsX > fAbsY ? fAbsX : fAbsY)); + + if(mnSteps > 2L && mnSteps < 128L) + { + fScaler = floor(fScaler * (double)mnSteps) / (double)(mnSteps - 1L); + } + + rBColor = (maStart * (1.0 - fScaler)) + (maEnd * fScaler); + } + } // end of namespace texture +} // end of namespace drawinglayer + +////////////////////////////////////////////////////////////////////////////// + +namespace drawinglayer +{ + namespace texture + { + geoTexSvxHatch::geoTexSvxHatch(const basegfx::B2DRange& rTargetRange, double fDistance, double fAngle) + : mfDistance(0.1), + mfAngle(fAngle), + mnSteps(10L) + { + double fTargetSizeX(rTargetRange.getWidth()); + double fTargetSizeY(rTargetRange.getHeight()); + double fTargetOffsetX(rTargetRange.getMinX()); + double fTargetOffsetY(rTargetRange.getMinY()); + + // add object expansion + if(0.0 != fAngle) + { + const double fAbsCos(fabs(cos(fAngle))); + const double fAbsSin(fabs(sin(fAngle))); + const double fNewX(fTargetSizeX * fAbsCos + fTargetSizeY * fAbsSin); + const double fNewY(fTargetSizeY * fAbsCos + fTargetSizeX * fAbsSin); + fTargetOffsetX -= (fNewX - fTargetSizeX) / 2.0; + fTargetOffsetY -= (fNewY - fTargetSizeY) / 2.0; + fTargetSizeX = fNewX; + fTargetSizeY = fNewY; + } + + // add object scale before rotate + maTextureTransform.scale(fTargetSizeX, fTargetSizeY); + + // add texture rotate after scale to keep perpendicular angles + if(0.0 != fAngle) + { + basegfx::B2DPoint aCenter(0.5, 0.5); + aCenter *= maTextureTransform; + + maTextureTransform.translate(-aCenter.getX(), -aCenter.getY()); + maTextureTransform.rotate(fAngle); + maTextureTransform.translate(aCenter.getX(), aCenter.getY()); + } + + // add object translate + maTextureTransform.translate(fTargetOffsetX, fTargetOffsetY); + + // prepare height for texture + const double fSteps((0.0 != fDistance) ? fTargetSizeY / fDistance : 10.0); + mnSteps = basegfx::fround(fSteps + 0.5); + mfDistance = 1.0 / fSteps; + + // build transform from u,v to [0.0 .. 1.0]. As base, use inverse texture transform + maBackTextureTransform = maTextureTransform; + maBackTextureTransform.invert(); + } + + geoTexSvxHatch::~geoTexSvxHatch() + { + } + + bool geoTexSvxHatch::operator==(const geoTexSvx& rGeoTexSvx) const + { + const geoTexSvxHatch* pCompare = dynamic_cast< const geoTexSvxHatch* >(&rGeoTexSvx); + return (pCompare + && maTextureTransform == pCompare->maTextureTransform + && mfDistance == pCompare->mfDistance + && mfAngle == pCompare->mfAngle + && mnSteps == pCompare->mnSteps); + } + + void geoTexSvxHatch::appendTransformations(::std::vector< basegfx::B2DHomMatrix >& rMatrices) + { + for(sal_uInt32 a(1L); a < mnSteps; a++) + { + // create matrix + const double fOffset(mfDistance * (double)a); + basegfx::B2DHomMatrix aNew; + aNew.set(1, 2, fOffset); + rMatrices.push_back(maTextureTransform * aNew); + } + } + + double geoTexSvxHatch::getDistanceToHatch(const basegfx::B2DPoint& rUV) const + { + const basegfx::B2DPoint aCoor(maBackTextureTransform * rUV); + return fmod(aCoor.getY(), mfDistance); + } + } // end of namespace texture +} // end of namespace drawinglayer + +////////////////////////////////////////////////////////////////////////////// + +namespace drawinglayer +{ + namespace texture + { + geoTexSvxTiled::geoTexSvxTiled(const basegfx::B2DPoint& rTopLeft, const basegfx::B2DVector& rSize) + : maTopLeft(rTopLeft), + maSize(rSize) + { + if(basegfx::fTools::lessOrEqual(maSize.getX(), 0.0)) + { + maSize.setX(1.0); + } + + if(basegfx::fTools::lessOrEqual(maSize.getY(), 0.0)) + { + maSize.setY(1.0); + } + } + + geoTexSvxTiled::~geoTexSvxTiled() + { + } + + bool geoTexSvxTiled::operator==(const geoTexSvx& rGeoTexSvx) const + { + const geoTexSvxTiled* pCompare = dynamic_cast< const geoTexSvxTiled* >(&rGeoTexSvx); + return (pCompare + && maTopLeft == pCompare->maTopLeft + && maSize == pCompare->maSize); + } + + void geoTexSvxTiled::appendTransformations(::std::vector< basegfx::B2DHomMatrix >& rMatrices) + { + double fStartX(maTopLeft.getX()); + double fStartY(maTopLeft.getY()); + + if(basegfx::fTools::more(fStartX, 0.0)) + { + fStartX -= (floor(fStartX / maSize.getX()) + 1.0) * maSize.getX(); + } + + if(basegfx::fTools::less(fStartX + maSize.getX(), 0.0)) + { + fStartX += floor(-fStartX / maSize.getX()) * maSize.getX(); + } + + if(basegfx::fTools::more(fStartY, 0.0)) + { + fStartY -= (floor(fStartY / maSize.getY()) + 1.0) * maSize.getY(); + } + + if(basegfx::fTools::less(fStartY + maSize.getY(), 0.0)) + { + fStartY += floor(-fStartY / maSize.getY()) * maSize.getY(); + } + + for(double fPosY(fStartY); basegfx::fTools::less(fPosY, 1.0); fPosY += maSize.getY()) + { + for(double fPosX(fStartX); basegfx::fTools::less(fPosX, 1.0); fPosX += maSize.getX()) + { + basegfx::B2DHomMatrix aNew; + + aNew.set(0, 0, maSize.getX()); + aNew.set(1, 1, maSize.getY()); + aNew.set(0, 2, fPosX); + aNew.set(1, 2, fPosY); + + rMatrices.push_back(aNew); + } + } + } + } // end of namespace texture +} // end of namespace drawinglayer + +////////////////////////////////////////////////////////////////////////////// +// eof diff --git a/drawinglayer/util/makefile.mk b/drawinglayer/util/makefile.mk index b2c089facf64..307ffd92b078 100644 --- a/drawinglayer/util/makefile.mk +++ b/drawinglayer/util/makefile.mk @@ -4,9 +4,9 @@ # # $RCSfile: makefile.mk,v $ # -# $Revision: 1.4 $ +# $Revision: 1.5 $ # -# last change: $Author: aw $ $Date: 2006-06-02 13:58:03 $ +# last change: $Author: aw $ $Date: 2006-08-09 16:58:53 $ # # The Contents of this file are made available subject to # the terms of GNU Lesser General Public License Version 2.1. @@ -50,7 +50,10 @@ LIB1FILES=\ $(SLB)$/primitive3d.lib \ $(SLB)$/geometry.lib \ $(SLB)$/processor.lib \ - $(SLB)$/animation.lib + $(SLB)$/processor3d.lib \ + $(SLB)$/attribute.lib \ + $(SLB)$/animation.lib \ + $(SLB)$/texture.lib SHL1TARGET= drawinglayer$(UPD)$(DLLPOSTFIX) SHL1IMPLIB= idrawinglayer |