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 
23 
24 // MARKER(update_precomp.py): autogen include statement, do not remove
25 #include "precompiled_drawinglayer.hxx"
26 
27 #include <drawinglayer/primitive3d/sdrdecompositiontools3d.hxx>
28 #include <basegfx/polygon/b3dpolygon.hxx>
29 #include <drawinglayer/attribute/strokeattribute.hxx>
30 #include <drawinglayer/primitive3d/baseprimitive3d.hxx>
31 #include <drawinglayer/primitive3d/polygonprimitive3d.hxx>
32 #include <basegfx/polygon/b3dpolypolygon.hxx>
33 #include <drawinglayer/primitive3d/polypolygonprimitive3d.hxx>
34 #include <vcl/vclenum.hxx>
35 #include <drawinglayer/attribute/fillgraphicattribute.hxx>
36 #include <drawinglayer/attribute/sdrfillgraphicattribute.hxx>
37 #include <vcl/bmpacc.hxx>
38 #include <basegfx/polygon/b3dpolypolygontools.hxx>
39 #include <drawinglayer/primitive3d/textureprimitive3d.hxx>
40 #include <drawinglayer/primitive3d/modifiedcolorprimitive3d.hxx>
41 #include <drawinglayer/primitive3d/hatchtextureprimitive3d.hxx>
42 #include <drawinglayer/primitive3d/shadowprimitive3d.hxx>
43 #include <basegfx/range/b2drange.hxx>
44 #include <drawinglayer/attribute/sdrlineattribute.hxx>
45 #include <drawinglayer/attribute/sdrobjectattribute3d.hxx>
46 #include <drawinglayer/attribute/sdrfillattribute.hxx>
47 #include <drawinglayer/attribute/sdrshadowattribute.hxx>
48 #include <drawinglayer/primitive3d/hiddengeometryprimitive3d.hxx>
49 
50 //////////////////////////////////////////////////////////////////////////////
51 
52 namespace drawinglayer
53 {
54 	namespace primitive3d
55 	{
getRangeFrom3DGeometry(::std::vector<basegfx::B3DPolyPolygon> & rFill)56 		basegfx::B3DRange getRangeFrom3DGeometry(::std::vector< basegfx::B3DPolyPolygon >& rFill)
57 		{
58 			basegfx::B3DRange aRetval;
59 
60 			for(sal_uInt32 a(0); a < rFill.size(); a++)
61 			{
62 				aRetval.expand(basegfx::tools::getRange(rFill[a]));
63 			}
64 
65 			return aRetval;
66 		}
67 
applyNormalsKindSphereTo3DGeometry(::std::vector<basegfx::B3DPolyPolygon> & rFill,const basegfx::B3DRange & rRange)68 		void applyNormalsKindSphereTo3DGeometry(::std::vector< basegfx::B3DPolyPolygon >& rFill, const basegfx::B3DRange& rRange)
69 		{
70 			// create sphere normals
71 			const basegfx::B3DPoint aCenter(rRange.getCenter());
72 
73 			for(sal_uInt32 a(0); a < rFill.size(); a++)
74 			{
75 				rFill[a] = basegfx::tools::applyDefaultNormalsSphere(rFill[a], aCenter);
76 			}
77 		}
78 
applyNormalsKindFlatTo3DGeometry(::std::vector<basegfx::B3DPolyPolygon> & rFill)79 		void applyNormalsKindFlatTo3DGeometry(::std::vector< basegfx::B3DPolyPolygon >& rFill)
80 		{
81 			for(sal_uInt32 a(0); a < rFill.size(); a++)
82 			{
83 				rFill[a].clearNormals();
84 			}
85 		}
86 
applyNormalsInvertTo3DGeometry(::std::vector<basegfx::B3DPolyPolygon> & rFill)87 		void applyNormalsInvertTo3DGeometry(::std::vector< basegfx::B3DPolyPolygon >& rFill)
88 		{
89 			// invert normals
90 			for(sal_uInt32 a(0); a < rFill.size(); a++)
91 			{
92 				rFill[a] = basegfx::tools::invertNormals(rFill[a]);
93 			}
94 		}
95 
applyTextureTo3DGeometry(::com::sun::star::drawing::TextureProjectionMode eModeX,::com::sun::star::drawing::TextureProjectionMode eModeY,::std::vector<basegfx::B3DPolyPolygon> & rFill,const basegfx::B3DRange & rRange,const basegfx::B2DVector & rTextureSize)96 		void applyTextureTo3DGeometry(
97 			::com::sun::star::drawing::TextureProjectionMode eModeX,
98 			::com::sun::star::drawing::TextureProjectionMode eModeY,
99 			::std::vector< basegfx::B3DPolyPolygon >& rFill,
100 			const basegfx::B3DRange& rRange,
101 			const basegfx::B2DVector& rTextureSize)
102 		{
103 			sal_uInt32 a;
104 
105 			// handle texture coordinates X
106 			const bool bParallelX(::com::sun::star::drawing::TextureProjectionMode_PARALLEL == eModeX);
107 			const bool bSphereX(!bParallelX && (::com::sun::star::drawing::TextureProjectionMode_SPHERE == eModeX));
108 
109 			// handle texture coordinates Y
110 			const bool bParallelY(::com::sun::star::drawing::TextureProjectionMode_PARALLEL == eModeY);
111 			const bool bSphereY(!bParallelY && (::com::sun::star::drawing::TextureProjectionMode_SPHERE == eModeY));
112 
113 			if(bParallelX || bParallelY)
114 			{
115 				// apply parallel texture coordinates in X and/or Y
116 				for(a = 0; a < rFill.size(); a++)
117 				{
118 					rFill[a] = basegfx::tools::applyDefaultTextureCoordinatesParallel(rFill[a], rRange, bParallelX, bParallelY);
119 				}
120 			}
121 
122 			if(bSphereX || bSphereY)
123 			{
124 				// apply spherical texture coordinates in X and/or Y
125 				const basegfx::B3DPoint aCenter(rRange.getCenter());
126 
127 				for(a = 0; a < rFill.size(); a++)
128 				{
129 					rFill[a] = basegfx::tools::applyDefaultTextureCoordinatesSphere(rFill[a], aCenter, bSphereX, bSphereY);
130 				}
131 			}
132 
133 			// transform texture coordinates to texture size
134 			basegfx::B2DHomMatrix aTexMatrix;
135 			aTexMatrix.scale(rTextureSize.getX(), rTextureSize.getY());
136 
137 			for(a = 0; a < rFill.size(); a++)
138 			{
139 				rFill[a].transformTextureCoordiantes(aTexMatrix);
140 			}
141 		}
142 
create3DPolyPolygonLinePrimitives(const basegfx::B3DPolyPolygon & rUnitPolyPolygon,const basegfx::B3DHomMatrix & rObjectTransform,const attribute::SdrLineAttribute & rLine)143 		Primitive3DSequence create3DPolyPolygonLinePrimitives(
144 			const basegfx::B3DPolyPolygon& rUnitPolyPolygon,
145 			const basegfx::B3DHomMatrix& rObjectTransform,
146 			const attribute::SdrLineAttribute& rLine)
147 		{
148 			// prepare fully scaled polyPolygon
149 			basegfx::B3DPolyPolygon aScaledPolyPolygon(rUnitPolyPolygon);
150 			aScaledPolyPolygon.transform(rObjectTransform);
151 
152 			// create line and stroke attribute
153 			const attribute::LineAttribute aLineAttribute(rLine.getColor(), rLine.getWidth(), rLine.getJoin(), rLine.getCap());
154 			const attribute::StrokeAttribute aStrokeAttribute(rLine.getDotDashArray(), rLine.getFullDotDashLen());
155 
156 			// create primitives
157 			Primitive3DSequence aRetval(aScaledPolyPolygon.count());
158 
159 			for(sal_uInt32 a(0L); a < aScaledPolyPolygon.count(); a++)
160 			{
161 				const Primitive3DReference xRef(new PolygonStrokePrimitive3D(aScaledPolyPolygon.getB3DPolygon(a), aLineAttribute, aStrokeAttribute));
162 				aRetval[a] = xRef;
163 			}
164 
165 			if(0.0 != rLine.getTransparence())
166 			{
167 				// create UnifiedTransparenceTexturePrimitive3D, add created primitives and exchange
168 				const Primitive3DReference xRef(new UnifiedTransparenceTexturePrimitive3D(rLine.getTransparence(), aRetval));
169 				aRetval = Primitive3DSequence(&xRef, 1L);
170 			}
171 
172 			return aRetval;
173 		}
174 
create3DPolyPolygonFillPrimitives(const::std::vector<basegfx::B3DPolyPolygon> & r3DPolyPolygonVector,const basegfx::B3DHomMatrix & rObjectTransform,const basegfx::B2DVector & rTextureSize,const attribute::Sdr3DObjectAttribute & aSdr3DObjectAttribute,const attribute::SdrFillAttribute & rFill,const attribute::FillGradientAttribute & rFillGradient)175 		Primitive3DSequence create3DPolyPolygonFillPrimitives(
176 			const ::std::vector< basegfx::B3DPolyPolygon >& r3DPolyPolygonVector,
177 			const basegfx::B3DHomMatrix& rObjectTransform,
178 			const basegfx::B2DVector& rTextureSize,
179 			const attribute::Sdr3DObjectAttribute& aSdr3DObjectAttribute,
180 			const attribute::SdrFillAttribute& rFill,
181 			const attribute::FillGradientAttribute& rFillGradient)
182 		{
183 			Primitive3DSequence aRetval;
184 
185 			if(r3DPolyPolygonVector.size())
186 			{
187 				// create list of simple fill primitives
188 				aRetval.realloc(r3DPolyPolygonVector.size());
189 
190 				for(sal_uInt32 a(0L); a < r3DPolyPolygonVector.size(); a++)
191 				{
192 					// get scaled PolyPolygon
193 					basegfx::B3DPolyPolygon aScaledPolyPolygon(r3DPolyPolygonVector[a]);
194 					aScaledPolyPolygon.transform(rObjectTransform);
195 
196 					if(aScaledPolyPolygon.areNormalsUsed())
197 					{
198 						aScaledPolyPolygon.transformNormals(rObjectTransform);
199 					}
200 
201 					const Primitive3DReference xRef(new PolyPolygonMaterialPrimitive3D(
202 						aScaledPolyPolygon,
203 						aSdr3DObjectAttribute.getMaterial(),
204 						aSdr3DObjectAttribute.getDoubleSided()));
205 					aRetval[a] = xRef;
206 				}
207 
208 				// look for and evtl. build texture sub-group primitive
209 				if(!rFill.getGradient().isDefault()
210 					|| !rFill.getHatch().isDefault()
211 					|| !rFill.getFillGraphic().isDefault())
212 				{
213 					bool bModulate(::com::sun::star::drawing::TextureMode_MODULATE == aSdr3DObjectAttribute.getTextureMode());
214 					bool bFilter(aSdr3DObjectAttribute.getTextureFilter());
215 					BasePrimitive3D* pNewTexturePrimitive3D = 0;
216 
217 					if(!rFill.getGradient().isDefault())
218 					{
219 						// create gradientTexture3D with sublist, add to local aRetval
220 						pNewTexturePrimitive3D = new GradientTexturePrimitive3D(
221                             rFill.getGradient(),
222                             aRetval,
223                             rTextureSize,
224                             bModulate,
225                             bFilter);
226 					}
227 					else if(!rFill.getHatch().isDefault())
228 					{
229 						// create hatchTexture3D with sublist, add to local aRetval
230 						pNewTexturePrimitive3D = new HatchTexturePrimitive3D(
231                             rFill.getHatch(),
232                             aRetval,
233                             rTextureSize,
234                             bModulate,
235                             bFilter);
236 					}
237 					else // if(!rFill.getFillGraphic().isDefault())
238 					{
239 						// create bitmapTexture3D with sublist, add to local aRetval
240 						const basegfx::B2DRange aTexRange(0.0, 0.0, rTextureSize.getX(), rTextureSize.getY());
241 
242                         pNewTexturePrimitive3D = new BitmapTexturePrimitive3D(
243                             rFill.getFillGraphic().createFillGraphicAttribute(aTexRange),
244                             aRetval,
245                             rTextureSize,
246                             bModulate,
247                             bFilter);
248 					}
249 
250 					// exchange aRetval content with texture group
251 					const Primitive3DReference xRef(pNewTexturePrimitive3D);
252 					aRetval = Primitive3DSequence(&xRef, 1L);
253 
254                     if(::com::sun::star::drawing::TextureKind2_LUMINANCE == aSdr3DObjectAttribute.getTextureKind())
255                     {
256                         // use modified color primitive to force textures to gray
257                         const basegfx::BColorModifierSharedPtr aBColorModifier(
258                             new basegfx::BColorModifier_gray());
259                         const Primitive3DReference xRef2(
260                             new ModifiedColorPrimitive3D(
261                                 aRetval,
262                                 aBColorModifier));
263 
264                         aRetval = Primitive3DSequence(&xRef2, 1L);
265                     }
266                 }
267 
268 				if(0.0 != rFill.getTransparence())
269 				{
270 					// create UnifiedTransparenceTexturePrimitive3D with sublist and exchange
271 					const Primitive3DReference xRef(new UnifiedTransparenceTexturePrimitive3D(rFill.getTransparence(), aRetval));
272 					aRetval = Primitive3DSequence(&xRef, 1L);
273 				}
274 				else if(!rFillGradient.isDefault())
275 				{
276 					// create TransparenceTexturePrimitive3D with sublist and exchange
277 					const Primitive3DReference xRef(new TransparenceTexturePrimitive3D(rFillGradient, aRetval, rTextureSize));
278 					aRetval = Primitive3DSequence(&xRef, 1L);
279 				}
280 			}
281 
282 			return aRetval;
283 		}
284 
createShadowPrimitive3D(const Primitive3DSequence & rSource,const attribute::SdrShadowAttribute & rShadow,bool bShadow3D)285 		Primitive3DSequence createShadowPrimitive3D(
286 			const Primitive3DSequence& rSource,
287 			const attribute::SdrShadowAttribute& rShadow,
288 			bool bShadow3D)
289 		{
290 			// create Shadow primitives. Uses already created primitives
291 			if(rSource.hasElements() && !basegfx::fTools::moreOrEqual(rShadow.getTransparence(), 1.0))
292 			{
293 				// prepare new list for shadow geometry
294 				basegfx::B2DHomMatrix aShadowOffset;
295 				aShadowOffset.set(0, 2, rShadow.getOffset().getX());
296 				aShadowOffset.set(1, 2, rShadow.getOffset().getY());
297 
298 				// create shadow primitive and add primitives
299 				const Primitive3DReference xRef(new ShadowPrimitive3D(aShadowOffset, rShadow.getColor(), rShadow.getTransparence(), bShadow3D, rSource));
300 				return Primitive3DSequence(&xRef, 1L);
301 			}
302 			else
303 			{
304 				return Primitive3DSequence();
305 			}
306 		}
307 
createHiddenGeometryPrimitives3D(const::std::vector<basegfx::B3DPolyPolygon> & r3DPolyPolygonVector,const basegfx::B3DHomMatrix & rObjectTransform,const basegfx::B2DVector & rTextureSize,const attribute::Sdr3DObjectAttribute & aSdr3DObjectAttribute)308         Primitive3DSequence createHiddenGeometryPrimitives3D(
309 			const ::std::vector< basegfx::B3DPolyPolygon >& r3DPolyPolygonVector,
310 			const basegfx::B3DHomMatrix& rObjectTransform,
311 			const basegfx::B2DVector& rTextureSize,
312 			const attribute::Sdr3DObjectAttribute& aSdr3DObjectAttribute)
313         {
314             // create hidden sub-geometry which can be used for HitTest
315             // and BoundRect calculations, but will not be visualized
316             const attribute::SdrFillAttribute aSimplifiedFillAttribute(
317                 0.0,
318                 basegfx::BColor(),
319                 attribute::FillGradientAttribute(),
320                 attribute::FillHatchAttribute(),
321                 attribute::SdrFillGraphicAttribute());
322 
323             const Primitive3DReference aHidden(
324                 new HiddenGeometryPrimitive3D(
325                     create3DPolyPolygonFillPrimitives(
326 		                r3DPolyPolygonVector,
327 		                rObjectTransform,
328 		                rTextureSize,
329 		                aSdr3DObjectAttribute,
330 		                aSimplifiedFillAttribute,
331 		                attribute::FillGradientAttribute())));
332 
333             return Primitive3DSequence(&aHidden, 1);
334         }
335 
336 	} // end of namespace primitive3d
337 } // end of namespace drawinglayer
338 
339 //////////////////////////////////////////////////////////////////////////////
340 // eof
341