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/texture/texture3d.hxx>
28 #include <vcl/bmpacc.hxx>
29 #include <drawinglayer/primitive3d/hatchtextureprimitive3d.hxx>
30 
31 //////////////////////////////////////////////////////////////////////////////
32 
33 namespace drawinglayer
34 {
35 	namespace texture
36 	{
37 		GeoTexSvxMono::GeoTexSvxMono(
38             const basegfx::BColor& rSingleColor,
39             double fOpacity)
40 		:	maSingleColor(rSingleColor),
41 			mfOpacity(fOpacity)
42 		{
43 		}
44 
45 		bool GeoTexSvxMono::operator==(const GeoTexSvx& rGeoTexSvx) const
46 		{
47 			const GeoTexSvxMono* pCompare = dynamic_cast< const GeoTexSvxMono* >(&rGeoTexSvx);
48 
49             return (pCompare
50 				&& maSingleColor == pCompare->maSingleColor
51 				&& mfOpacity == pCompare->mfOpacity);
52 		}
53 
54 		void GeoTexSvxMono::modifyBColor(const basegfx::B2DPoint& /*rUV*/, basegfx::BColor& rBColor, double& /*rfOpacity*/) const
55 		{
56 			rBColor = maSingleColor;
57 		}
58 
59 		void GeoTexSvxMono::modifyOpacity(const basegfx::B2DPoint& /*rUV*/, double& rfOpacity) const
60 		{
61 			rfOpacity = mfOpacity;
62 		}
63 	} // end of namespace texture
64 } // end of namespace drawinglayer
65 
66 //////////////////////////////////////////////////////////////////////////////
67 
68 namespace drawinglayer
69 {
70 	namespace texture
71 	{
72 		GeoTexSvxBitmapEx::GeoTexSvxBitmapEx(
73             const BitmapEx& rBitmapEx,
74             const basegfx::B2DRange& rRange)
75 		:	maBitmapEx(rBitmapEx),
76 			mpReadBitmap(0),
77             maTransparence(),
78             mpReadTransparence(0),
79 			maTopLeft(rRange.getMinimum()),
80 			maSize(rRange.getRange()),
81 			mfMulX(0.0),
82 			mfMulY(0.0),
83             mbIsAlpha(false),
84             mbIsTransparent(maBitmapEx.IsTransparent())
85 		{
86             // #121194# Todo: use alpha channel, too (for 3d)
87 			mpReadBitmap = maBitmapEx.GetBitmap().AcquireReadAccess();
88 			OSL_ENSURE(mpReadBitmap, "GeoTexSvxBitmapEx: Got no read access to Bitmap (!)");
89 
90             if(mbIsTransparent)
91             {
92                 if(maBitmapEx.IsAlpha())
93                 {
94                     mbIsAlpha = true;
95                     maTransparence = rBitmapEx.GetAlpha().GetBitmap();
96                 }
97                 else
98                 {
99                     maTransparence = rBitmapEx.GetMask();
100                 }
101 
102                 mpReadTransparence = maTransparence.AcquireReadAccess();
103             }
104 
105             mfMulX = (double)mpReadBitmap->Width() / maSize.getX();
106 			mfMulY = (double)mpReadBitmap->Height() / maSize.getY();
107 
108             if(maSize.getX() <= 1.0)
109             {
110                 maSize.setX(1.0);
111             }
112 
113             if(maSize.getY() <= 1.0)
114             {
115                 maSize.setY(1.0);
116             }
117 		}
118 
119 		GeoTexSvxBitmapEx::~GeoTexSvxBitmapEx()
120 		{
121             delete mpReadTransparence;
122 			delete mpReadBitmap;
123 		}
124 
125         sal_uInt8 GeoTexSvxBitmapEx::impGetTransparence(sal_Int32& rX, sal_Int32& rY) const
126         {
127             switch(maBitmapEx.GetTransparentType())
128             {
129                 case TRANSPARENT_NONE:
130                 {
131                     break;
132                 }
133                 case TRANSPARENT_COLOR:
134                 {
135                     const BitmapColor aBitmapColor(mpReadBitmap->GetColor(rY, rX));
136 
137                     if(maBitmapEx.GetTransparentColor() == Color(aBitmapColor))
138                     {
139                         return 255;
140                     }
141 
142                     break;
143                 }
144                 case TRANSPARENT_BITMAP:
145                 {
146                     OSL_ENSURE(mpReadTransparence, "OOps, transparence type Bitmap, but no read access created in the constructor (?)");
147                     const BitmapColor aBitmapColor(mpReadTransparence->GetPixel(rY, rX));
148 
149                     if(mbIsAlpha)
150                     {
151                         return aBitmapColor.GetIndex();
152                     }
153                     else
154                     {
155                         if(0x00 != aBitmapColor.GetIndex())
156                         {
157                             return 255;
158                         }
159                     }
160                     break;
161                 }
162             }
163 
164             return 0;
165         }
166 
167 		bool GeoTexSvxBitmapEx::impIsValid(const basegfx::B2DPoint& rUV, sal_Int32& rX, sal_Int32& rY) const
168 		{
169 			if(mpReadBitmap)
170 			{
171 				rX = (sal_Int32)((rUV.getX() - maTopLeft.getX()) * mfMulX);
172 
173 				if(rX >= 0L && rX < mpReadBitmap->Width())
174 				{
175 					rY = (sal_Int32)((rUV.getY() - maTopLeft.getY()) * mfMulY);
176 
177 					return (rY >= 0L && rY < mpReadBitmap->Height());
178 				}
179 			}
180 
181 			return false;
182 		}
183 
184 		void GeoTexSvxBitmapEx::modifyBColor(const basegfx::B2DPoint& rUV, basegfx::BColor& rBColor, double& rfOpacity) const
185 		{
186 			sal_Int32 nX, nY;
187 
188 			if(impIsValid(rUV, nX, nY))
189 			{
190 				const double fConvertColor(1.0 / 255.0);
191 				const BitmapColor aBMCol(mpReadBitmap->GetColor(nY, nX));
192 				const basegfx::BColor aBSource(
193 					(double)aBMCol.GetRed() * fConvertColor,
194 					(double)aBMCol.GetGreen() * fConvertColor,
195 					(double)aBMCol.GetBlue() * fConvertColor);
196 
197 				rBColor = aBSource;
198 
199                 if(mbIsTransparent)
200                 {
201                     // when we have a transparence, make use of it
202                     const sal_uInt8 aLuminance(impGetTransparence(nX, nY));
203 
204                     rfOpacity = ((double)(0xff - aLuminance) * (1.0 / 255.0));
205                 }
206                 else
207                 {
208                     rfOpacity = 1.0;
209                 }
210 			}
211 			else
212 			{
213 				rfOpacity = 0.0;
214 			}
215 		}
216 
217 		void GeoTexSvxBitmapEx::modifyOpacity(const basegfx::B2DPoint& rUV, double& rfOpacity) const
218 		{
219 			sal_Int32 nX, nY;
220 
221 			if(impIsValid(rUV, nX, nY))
222 			{
223                 if(mbIsTransparent)
224                 {
225                     // this texture has an alpha part, use it
226                     const sal_uInt8 aLuminance(impGetTransparence(nX, nY));
227                     const double fNewOpacity((double)(0xff - aLuminance) * (1.0 / 255.0));
228 
229                     rfOpacity = 1.0 - ((1.0 - fNewOpacity) * (1.0 - rfOpacity));
230                 }
231                 else
232                 {
233                     // this texture is a color bitmap used as transparence map
234 				    const BitmapColor aBMCol(mpReadBitmap->GetColor(nY, nX));
235 				    const Color aColor(aBMCol.GetRed(), aBMCol.GetGreen(), aBMCol.GetBlue());
236 
237 				    rfOpacity = ((double)(0xff - aColor.GetLuminance()) * (1.0 / 255.0));
238                 }
239 			}
240 			else
241 			{
242 				rfOpacity = 0.0;
243 			}
244 		}
245 	} // end of namespace texture
246 } // end of namespace drawinglayer
247 
248 //////////////////////////////////////////////////////////////////////////////
249 
250 namespace drawinglayer
251 {
252 	namespace texture
253 	{
254 		basegfx::B2DPoint GeoTexSvxBitmapExTiled::impGetCorrected(const basegfx::B2DPoint& rUV) const
255 		{
256             double fX(rUV.getX() - maTopLeft.getX());
257             double fY(rUV.getY() - maTopLeft.getY());
258 
259             if(mbUseOffsetX)
260             {
261                 const sal_Int32 nCol(static_cast< sal_Int32 >((fY < 0.0 ? maSize.getY() -fY : fY) / maSize.getY()));
262 
263                 if(nCol % 2)
264                 {
265                     fX += mfOffsetX * maSize.getX();
266                 }
267             }
268             else if(mbUseOffsetY)
269             {
270                 const sal_Int32 nRow(static_cast< sal_Int32 >((fX < 0.0 ? maSize.getX() -fX : fX) / maSize.getX()));
271 
272                 if(nRow % 2)
273                 {
274                     fY += mfOffsetY * maSize.getY();
275                 }
276             }
277 
278             fX = fmod(fX, maSize.getX());
279             fY = fmod(fY, maSize.getY());
280 
281             if(fX < 0.0)
282             {
283                 fX += maSize.getX();
284             }
285 
286             if(fY < 0.0)
287             {
288                 fY += maSize.getY();
289             }
290 
291             return basegfx::B2DPoint(fX + maTopLeft.getX(), fY + maTopLeft.getY());
292 		}
293 
294         GeoTexSvxBitmapExTiled::GeoTexSvxBitmapExTiled(
295             const BitmapEx& rBitmapEx,
296             const basegfx::B2DRange& rRange,
297             double fOffsetX,
298             double fOffsetY)
299 		:	GeoTexSvxBitmapEx(rBitmapEx, rRange),
300             mfOffsetX(basegfx::clamp(fOffsetX, 0.0, 1.0)),
301             mfOffsetY(basegfx::clamp(fOffsetY, 0.0, 1.0)),
302             mbUseOffsetX(!basegfx::fTools::equalZero(mfOffsetX)),
303             mbUseOffsetY(!mbUseOffsetX && !basegfx::fTools::equalZero(mfOffsetY))
304 		{
305 		}
306 
307 		void GeoTexSvxBitmapExTiled::modifyBColor(const basegfx::B2DPoint& rUV, basegfx::BColor& rBColor, double& rfOpacity) const
308 		{
309 			if(mpReadBitmap)
310 			{
311 				GeoTexSvxBitmapEx::modifyBColor(impGetCorrected(rUV), rBColor, rfOpacity);
312 			}
313 		}
314 
315 		void GeoTexSvxBitmapExTiled::modifyOpacity(const basegfx::B2DPoint& rUV, double& rfOpacity) const
316 		{
317 			if(mpReadBitmap)
318 			{
319 				GeoTexSvxBitmapEx::modifyOpacity(impGetCorrected(rUV), rfOpacity);
320 			}
321 		}
322 	} // end of namespace texture
323 } // end of namespace drawinglayer
324 
325 //////////////////////////////////////////////////////////////////////////////
326 
327 namespace drawinglayer
328 {
329 	namespace texture
330 	{
331 		GeoTexSvxMultiHatch::GeoTexSvxMultiHatch(
332             const primitive3d::HatchTexturePrimitive3D& rPrimitive,
333             double fLogicPixelSize)
334 		:	mfLogicPixelSize(fLogicPixelSize),
335 			mp0(0L),
336 			mp1(0L),
337 			mp2(0L)
338 		{
339 			const attribute::FillHatchAttribute& rHatch(rPrimitive.getHatch());
340 			const basegfx::B2DRange aOutlineRange(0.0, 0.0, rPrimitive.getTextureSize().getX(), rPrimitive.getTextureSize().getY());
341 			const double fAngleA(rHatch.getAngle());
342 			maColor = rHatch.getColor();
343 			mbFillBackground = rHatch.isFillBackground();
344 			mp0 = new GeoTexSvxHatch(aOutlineRange, rHatch.getDistance(), fAngleA);
345 
346 			if(attribute::HATCHSTYLE_DOUBLE == rHatch.getStyle() || attribute::HATCHSTYLE_TRIPLE == rHatch.getStyle())
347 			{
348 				mp1 = new GeoTexSvxHatch(aOutlineRange, rHatch.getDistance(), fAngleA + F_PI2);
349 			}
350 
351 			if(attribute::HATCHSTYLE_TRIPLE == rHatch.getStyle())
352 			{
353 				mp2 = new GeoTexSvxHatch(aOutlineRange, rHatch.getDistance(), fAngleA + F_PI4);
354 			}
355 		}
356 
357 		GeoTexSvxMultiHatch::~GeoTexSvxMultiHatch()
358 		{
359 			delete mp0;
360 			delete mp1;
361 			delete mp2;
362 		}
363 
364 		bool GeoTexSvxMultiHatch::impIsOnHatch(const basegfx::B2DPoint& rUV) const
365 		{
366 			if(mp0->getDistanceToHatch(rUV) < mfLogicPixelSize)
367 			{
368 				return true;
369 			}
370 
371 			if(mp1 && mp1->getDistanceToHatch(rUV) < mfLogicPixelSize)
372 			{
373 				return true;
374 			}
375 
376 			if(mp2 && mp2->getDistanceToHatch(rUV) < mfLogicPixelSize)
377 			{
378 				return true;
379 			}
380 
381 			return false;
382 		}
383 
384 		void GeoTexSvxMultiHatch::modifyBColor(const basegfx::B2DPoint& rUV, basegfx::BColor& rBColor, double& rfOpacity) const
385 		{
386 			if(impIsOnHatch(rUV))
387 			{
388 				rBColor = maColor;
389 			}
390 			else if(!mbFillBackground)
391 			{
392 				rfOpacity = 0.0;
393 			}
394 		}
395 
396 		void GeoTexSvxMultiHatch::modifyOpacity(const basegfx::B2DPoint& rUV, double& rfOpacity) const
397 		{
398 			if(mbFillBackground || impIsOnHatch(rUV))
399 			{
400 				rfOpacity = 1.0;
401 			}
402 			else
403 			{
404 				rfOpacity = 0.0;
405 			}
406 		}
407 	} // end of namespace texture
408 } // end of namespace drawinglayer
409 
410 //////////////////////////////////////////////////////////////////////////////
411 // eof
412