1 /**************************************************************
2  *
3  * Licensed to the Apache Software Foundation (ASF) under one
4  * or more contributor license agreements.  See the NOTICE file
5  * distributed with this work for additional information
6  * regarding copyright ownership.  The ASF licenses this file
7  * to you under the Apache License, Version 2.0 (the
8  * "License"); you may not use this file except in compliance
9  * with the License.  You may obtain a copy of the License at
10  *
11  *   http://www.apache.org/licenses/LICENSE-2.0
12  *
13  * Unless required by applicable law or agreed to in writing,
14  * software distributed under the License is distributed on an
15  * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
16  * KIND, either express or implied.  See the License for the
17  * specific language governing permissions and limitations
18  * under the License.
19  *
20  *************************************************************/
21 
22 // MARKER(update_precomp.py): autogen include statement, do not remove
23 #include "precompiled_drawinglayer.hxx"
24 
25 #include <drawinglayer/attribute/sdrlightingattribute3d.hxx>
26 #include <basegfx/color/bcolor.hxx>
27 #include <basegfx/vector/b3dvector.hxx>
28 #include <drawinglayer/attribute/sdrlightattribute3d.hxx>
29 
30 //////////////////////////////////////////////////////////////////////////////
31 
32 namespace drawinglayer
33 {
34 	namespace attribute
35 	{
36 		class ImpSdrLightingAttribute
37 		{
38 		public:
39 			// refcounter
40 			sal_uInt32								mnRefCount;
41 
42 			// 3D light attribute definitions
43 			basegfx::BColor							maAmbientLight;
44 			::std::vector< Sdr3DLightAttribute >	maLightVector;
45 
ImpSdrLightingAttribute(const basegfx::BColor & rAmbientLight,const::std::vector<Sdr3DLightAttribute> & rLightVector)46 			ImpSdrLightingAttribute(
47 				const basegfx::BColor& rAmbientLight,
48 				const ::std::vector< Sdr3DLightAttribute >& rLightVector)
49 			:	mnRefCount(0),
50 		    	maAmbientLight(rAmbientLight),
51 			    maLightVector(rLightVector)
52 		    {
53 		    }
54 
55 			// data read access
getAmbientLight() const56 			const basegfx::BColor& getAmbientLight() const { return maAmbientLight; }
getLightVector() const57 			const ::std::vector< Sdr3DLightAttribute >& getLightVector() const { return maLightVector; }
58 
operator ==(const ImpSdrLightingAttribute & rCandidate) const59             bool operator==(const ImpSdrLightingAttribute& rCandidate) const
60 		    {
61 			    return (getAmbientLight() == rCandidate.getAmbientLight()
62 				    && getLightVector() == rCandidate.getLightVector());
63 		    }
64 
get_global_default()65             static ImpSdrLightingAttribute* get_global_default()
66             {
67                 static ImpSdrLightingAttribute* pDefault = 0;
68 
69                 if(!pDefault)
70                 {
71                     pDefault = new ImpSdrLightingAttribute(
72 			            basegfx::BColor(),
73 			            std::vector< Sdr3DLightAttribute >());
74 
75                     // never delete; start with RefCount 1, not 0
76     			    pDefault->mnRefCount++;
77                 }
78 
79                 return pDefault;
80             }
81 		};
82 
SdrLightingAttribute(const basegfx::BColor & rAmbientLight,const::std::vector<Sdr3DLightAttribute> & rLightVector)83         SdrLightingAttribute::SdrLightingAttribute(
84 			const basegfx::BColor& rAmbientLight,
85 			const ::std::vector< Sdr3DLightAttribute >& rLightVector)
86 		:	mpSdrLightingAttribute(new ImpSdrLightingAttribute(
87                 rAmbientLight, rLightVector))
88 		{
89 		}
90 
SdrLightingAttribute()91 		SdrLightingAttribute::SdrLightingAttribute()
92         :	mpSdrLightingAttribute(ImpSdrLightingAttribute::get_global_default())
93 		{
94 			mpSdrLightingAttribute->mnRefCount++;
95 		}
96 
SdrLightingAttribute(const SdrLightingAttribute & rCandidate)97         SdrLightingAttribute::SdrLightingAttribute(const SdrLightingAttribute& rCandidate)
98 		:	mpSdrLightingAttribute(rCandidate.mpSdrLightingAttribute)
99 		{
100 			mpSdrLightingAttribute->mnRefCount++;
101 		}
102 
~SdrLightingAttribute()103 		SdrLightingAttribute::~SdrLightingAttribute()
104 		{
105 			if(mpSdrLightingAttribute->mnRefCount)
106 			{
107 				mpSdrLightingAttribute->mnRefCount--;
108 			}
109 			else
110 			{
111 				delete mpSdrLightingAttribute;
112 			}
113 		}
114 
isDefault() const115         bool SdrLightingAttribute::isDefault() const
116         {
117             return mpSdrLightingAttribute == ImpSdrLightingAttribute::get_global_default();
118         }
119 
operator =(const SdrLightingAttribute & rCandidate)120         SdrLightingAttribute& SdrLightingAttribute::operator=(const SdrLightingAttribute& rCandidate)
121 		{
122 			if(rCandidate.mpSdrLightingAttribute != mpSdrLightingAttribute)
123 			{
124 				if(mpSdrLightingAttribute->mnRefCount)
125 				{
126 					mpSdrLightingAttribute->mnRefCount--;
127 				}
128 				else
129 				{
130 					delete mpSdrLightingAttribute;
131 				}
132 
133 				mpSdrLightingAttribute = rCandidate.mpSdrLightingAttribute;
134 				mpSdrLightingAttribute->mnRefCount++;
135 			}
136 
137 			return *this;
138 		}
139 
operator ==(const SdrLightingAttribute & rCandidate) const140 		bool SdrLightingAttribute::operator==(const SdrLightingAttribute& rCandidate) const
141 		{
142 			if(rCandidate.mpSdrLightingAttribute == mpSdrLightingAttribute)
143 			{
144 				return true;
145 			}
146 
147 			if(rCandidate.isDefault() != isDefault())
148 			{
149 				return false;
150 			}
151 
152 			return (*rCandidate.mpSdrLightingAttribute == *mpSdrLightingAttribute);
153 		}
154 
getAmbientLight() const155 		const basegfx::BColor& SdrLightingAttribute::getAmbientLight() const
156         {
157             return mpSdrLightingAttribute->getAmbientLight();
158         }
159 
getLightVector() const160         const ::std::vector< Sdr3DLightAttribute >& SdrLightingAttribute::getLightVector() const
161         {
162             return mpSdrLightingAttribute->getLightVector();
163         }
164 
165         // color model solver
solveColorModel(const basegfx::B3DVector & rNormalInEyeCoordinates,const basegfx::BColor & rColor,const basegfx::BColor & rSpecular,const basegfx::BColor & rEmission,sal_uInt16 nSpecularIntensity) const166 		basegfx::BColor SdrLightingAttribute::solveColorModel(
167 			const basegfx::B3DVector& rNormalInEyeCoordinates,
168 			const basegfx::BColor& rColor, const basegfx::BColor& rSpecular,
169 			const basegfx::BColor& rEmission, sal_uInt16 nSpecularIntensity) const
170 		{
171 			// initialize with emissive color
172 			basegfx::BColor aRetval(rEmission);
173 
174 			// take care of global ambient light
175 			aRetval += mpSdrLightingAttribute->getAmbientLight() * rColor;
176 
177 			// prepare light access. Is there a light?
178 			const sal_uInt32 nLightCount(mpSdrLightingAttribute->getLightVector().size());
179 
180 			if(nLightCount && !rNormalInEyeCoordinates.equalZero())
181 			{
182 				// prepare normal
183 				basegfx::B3DVector aEyeNormal(rNormalInEyeCoordinates);
184 				aEyeNormal.normalize();
185 
186 				for(sal_uInt32 a(0L); a < nLightCount; a++)
187 				{
188 					const Sdr3DLightAttribute& rLight(mpSdrLightingAttribute->getLightVector()[a]);
189 					const double fCosFac(rLight.getDirection().scalar(aEyeNormal));
190 
191 					if(basegfx::fTools::more(fCosFac, 0.0))
192 					{
193 						aRetval += ((rLight.getColor() * rColor) * fCosFac);
194 
195 						if(rLight.getSpecular())
196 						{
197 							// expand by (0.0, 0.0, 1.0) in Z
198 							basegfx::B3DVector aSpecularNormal(rLight.getDirection().getX(), rLight.getDirection().getY(), rLight.getDirection().getZ() + 1.0);
199 							aSpecularNormal.normalize();
200 							double fCosFac2(aSpecularNormal.scalar(aEyeNormal));
201 
202 							if(basegfx::fTools::more(fCosFac2, 0.0))
203 							{
204 								fCosFac2 = pow(fCosFac2, (double)nSpecularIntensity);
205 								aRetval += (rSpecular * fCosFac2);
206 							}
207 						}
208 					}
209 				}
210 			}
211 
212 			// clamp to color space before usage
213 			aRetval.clamp();
214 
215 			return aRetval;
216 		}
217 	} // end of namespace attribute
218 } // end of namespace drawinglayer
219 
220 //////////////////////////////////////////////////////////////////////////////
221 // eof
222