1 /*************************************************************************
2  *
3  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4  *
5  * Copyright 2000, 2010 Oracle and/or its affiliates.
6  *
7  * OpenOffice.org - a multi-platform office productivity suite
8  *
9  * This file is part of OpenOffice.org.
10  *
11  * OpenOffice.org is free software: you can redistribute it and/or modify
12  * it under the terms of the GNU Lesser General Public License version 3
13  * only, as published by the Free Software Foundation.
14  *
15  * OpenOffice.org is distributed in the hope that it will be useful,
16  * but WITHOUT ANY WARRANTY; without even the implied warranty of
17  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
18  * GNU Lesser General Public License version 3 for more details
19  * (a copy is included in the LICENSE file that accompanied this code).
20  *
21  * You should have received a copy of the GNU Lesser General Public License
22  * version 3 along with OpenOffice.org.  If not, see
23  * <http://www.openoffice.org/license.html>
24  * for a copy of the LGPLv3 License.
25  *
26  ************************************************************************/
27 
28 // MARKER(update_precomp.py): autogen include statement, do not remove
29 #include "precompiled_drawinglayer.hxx"
30 
31 #include <drawinglayer/attribute/sdrfillbitmapattribute.hxx>
32 #include <drawinglayer/attribute/fillbitmapattribute.hxx>
33 #include <vcl/bitmapex.hxx>
34 
35 //////////////////////////////////////////////////////////////////////////////
36 
37 namespace drawinglayer
38 {
39 	namespace attribute
40 	{
41 		class ImpSdrFillBitmapAttribute
42 		{
43         public:
44 		    // refcounter
45 		    sal_uInt32								mnRefCount;
46 
47             // data definitions
48 			Bitmap									maBitmap;
49 			basegfx::B2DVector						maSize;
50 			basegfx::B2DVector						maOffset;
51 			basegfx::B2DVector						maOffsetPosition;
52 			basegfx::B2DVector						maRectPoint;
53 
54 			// bitfield
55 			unsigned								mbTiling : 1;
56 			unsigned								mbStretch : 1;
57 			unsigned								mbLogSize : 1;
58 
59 			ImpSdrFillBitmapAttribute(
60 				const Bitmap& rBitmap,
61                 const basegfx::B2DVector& rSize,
62                 const basegfx::B2DVector& rOffset,
63 				const basegfx::B2DVector& rOffsetPosition,
64                 const basegfx::B2DVector& rRectPoint,
65 				bool bTiling,
66                 bool bStretch,
67                 bool bLogSize)
68 		    :	mnRefCount(0),
69 		    	maBitmap(rBitmap),
70 			    maSize(rSize),
71 			    maOffset(rOffset),
72 			    maOffsetPosition(rOffsetPosition),
73 			    maRectPoint(rRectPoint),
74 			    mbTiling(bTiling),
75 			    mbStretch(bStretch),
76 			    mbLogSize(bLogSize)
77 		    {
78 		    }
79 
80 			// data read access
81             const Bitmap& getBitmap() const { return maBitmap; }
82             const basegfx::B2DVector& getSize() const { return maSize; }
83             const basegfx::B2DVector& getOffset() const { return maOffset; }
84             const basegfx::B2DVector& getOffsetPosition() const { return maOffsetPosition; }
85             const basegfx::B2DVector& getRectPoint() const { return maRectPoint; }
86             bool getTiling() const { return mbTiling; }
87             bool getStretch() const { return mbStretch; }
88             bool getLogSize() const { return mbLogSize; }
89 
90             bool operator==(const ImpSdrFillBitmapAttribute& rCandidate) const
91             {
92 			    return (getBitmap() == rCandidate.getBitmap()
93 				    && getSize() == rCandidate.getSize()
94 				    && getOffset() == rCandidate.getOffset()
95 				    && getOffsetPosition() == rCandidate.getOffsetPosition()
96 				    && getRectPoint() == rCandidate.getRectPoint()
97 				    && getTiling() == rCandidate.getTiling()
98 				    && getStretch() == rCandidate.getStretch()
99 				    && getLogSize() == rCandidate.getLogSize());
100             }
101 
102             static ImpSdrFillBitmapAttribute* get_global_default()
103             {
104                 static ImpSdrFillBitmapAttribute* pDefault = 0;
105 
106                 if(!pDefault)
107                 {
108                     pDefault = new ImpSdrFillBitmapAttribute(
109 			            Bitmap(),
110                         basegfx::B2DVector(),
111                         basegfx::B2DVector(),
112 			            basegfx::B2DVector(),
113                         basegfx::B2DVector(),
114 			            false,
115                         false,
116                         false);
117 
118                     // never delete; start with RefCount 1, not 0
119     			    pDefault->mnRefCount++;
120                 }
121 
122                 return pDefault;
123             }
124 		};
125 
126         SdrFillBitmapAttribute::SdrFillBitmapAttribute(
127 			const Bitmap& rBitmap,
128             const basegfx::B2DVector& rSize,
129             const basegfx::B2DVector& rOffset,
130 			const basegfx::B2DVector& rOffsetPosition,
131             const basegfx::B2DVector& rRectPoint,
132 			bool bTiling,
133             bool bStretch,
134             bool bLogSize)
135 		:	mpSdrFillBitmapAttribute(new ImpSdrFillBitmapAttribute(
136                 rBitmap, rSize, rOffset, rOffsetPosition, rRectPoint, bTiling,  bStretch, bLogSize))
137 		{
138 		}
139 
140 		SdrFillBitmapAttribute::SdrFillBitmapAttribute()
141         :	mpSdrFillBitmapAttribute(ImpSdrFillBitmapAttribute::get_global_default())
142 		{
143 			mpSdrFillBitmapAttribute->mnRefCount++;
144 		}
145 
146         SdrFillBitmapAttribute::SdrFillBitmapAttribute(const SdrFillBitmapAttribute& rCandidate)
147 		:	mpSdrFillBitmapAttribute(rCandidate.mpSdrFillBitmapAttribute)
148 		{
149 			mpSdrFillBitmapAttribute->mnRefCount++;
150 		}
151 
152 		SdrFillBitmapAttribute::~SdrFillBitmapAttribute()
153 		{
154 			if(mpSdrFillBitmapAttribute->mnRefCount)
155 			{
156 				mpSdrFillBitmapAttribute->mnRefCount--;
157 			}
158 			else
159 			{
160 				delete mpSdrFillBitmapAttribute;
161 			}
162 		}
163 
164         bool SdrFillBitmapAttribute::isDefault() const
165         {
166             return mpSdrFillBitmapAttribute == ImpSdrFillBitmapAttribute::get_global_default();
167         }
168 
169         SdrFillBitmapAttribute& SdrFillBitmapAttribute::operator=(const SdrFillBitmapAttribute& rCandidate)
170 		{
171 			if(rCandidate.mpSdrFillBitmapAttribute != mpSdrFillBitmapAttribute)
172 			{
173 				if(mpSdrFillBitmapAttribute->mnRefCount)
174 				{
175 					mpSdrFillBitmapAttribute->mnRefCount--;
176 				}
177 				else
178 				{
179 					delete mpSdrFillBitmapAttribute;
180 				}
181 
182 				mpSdrFillBitmapAttribute = rCandidate.mpSdrFillBitmapAttribute;
183 				mpSdrFillBitmapAttribute->mnRefCount++;
184 			}
185 
186 			return *this;
187 		}
188 
189 		bool SdrFillBitmapAttribute::operator==(const SdrFillBitmapAttribute& rCandidate) const
190 		{
191 			if(rCandidate.mpSdrFillBitmapAttribute == mpSdrFillBitmapAttribute)
192 			{
193 				return true;
194 			}
195 
196 			if(rCandidate.isDefault() != isDefault())
197 			{
198 				return false;
199 			}
200 
201 			return (*rCandidate.mpSdrFillBitmapAttribute == *mpSdrFillBitmapAttribute);
202 		}
203 
204         const Bitmap& SdrFillBitmapAttribute::getBitmap() const
205         {
206             return mpSdrFillBitmapAttribute->getBitmap();
207         }
208 
209         const basegfx::B2DVector& SdrFillBitmapAttribute::getSize() const
210         {
211             return mpSdrFillBitmapAttribute->getSize();
212         }
213 
214         const basegfx::B2DVector& SdrFillBitmapAttribute::getOffset() const
215         {
216             return mpSdrFillBitmapAttribute->getOffset();
217         }
218 
219         const basegfx::B2DVector& SdrFillBitmapAttribute::getOffsetPosition() const
220         {
221             return mpSdrFillBitmapAttribute->getOffsetPosition();
222         }
223 
224         const basegfx::B2DVector& SdrFillBitmapAttribute::getRectPoint() const
225         {
226             return mpSdrFillBitmapAttribute->getRectPoint();
227         }
228 
229         bool SdrFillBitmapAttribute::getTiling() const
230         {
231             return mpSdrFillBitmapAttribute->getTiling();
232         }
233 
234         bool SdrFillBitmapAttribute::getStretch() const
235         {
236             return mpSdrFillBitmapAttribute->getStretch();
237         }
238 
239         bool SdrFillBitmapAttribute::getLogSize() const
240         {
241             return mpSdrFillBitmapAttribute->getLogSize();
242         }
243 
244         FillBitmapAttribute SdrFillBitmapAttribute::getFillBitmapAttribute(const basegfx::B2DRange& rRange) const
245 		{
246 			// get logical size of bitmap (before expanding eventually)
247 			Bitmap aBitmap(getBitmap());
248 			const basegfx::B2DVector aLogicalSize(aBitmap.GetPrefSize().getWidth(), aBitmap.GetPrefSize().getHeight());
249 
250 			// get hor/ver shiftings and apply them eventually to the bitmap, but only
251 			// when tiling is on
252 			bool bExpandWidth(false);
253 			bool bExpandHeight(false);
254 
255 			if(getTiling())
256 			{
257 				if(0.0 != getOffset().getX() || 0.0 != getOffset().getY())
258 				{
259 					const sal_uInt32 nWidth(aBitmap.GetSizePixel().getWidth());
260 					const sal_uInt32 nHeight(aBitmap.GetSizePixel().getHeight());
261 
262 					if(0.0 != getOffset().getX())
263 					{
264 						bExpandHeight = true;
265 						const sal_uInt32 nOffset(basegfx::fround(((double)nWidth * getOffset().getX()) / 100.0));
266 						aBitmap.Expand(0L, nHeight);
267 
268 						const Size aSizeA(nOffset, nHeight);
269 						const Rectangle aDstA(Point(0L, nHeight), aSizeA);
270 						const Rectangle aSrcA(Point(nWidth - nOffset, 0L), aSizeA);
271 						aBitmap.CopyPixel(aDstA, aSrcA);
272 
273 						const Size aSizeB(nWidth - nOffset, nHeight);
274 						const Rectangle aDstB(Point(nOffset, nHeight), aSizeB);
275 						const Rectangle aSrcB(Point(0L, 0L), aSizeB);
276 						aBitmap.CopyPixel(aDstB, aSrcB);
277 					}
278 					else
279 					{
280 						bExpandWidth = true;
281 						const sal_uInt32 nOffset(basegfx::fround(((double)nHeight * getOffset().getY()) / 100.0));
282 						aBitmap.Expand(nWidth, 0L);
283 
284 						const Size aSize(nWidth, nHeight);
285 						const Rectangle aDst(Point(nWidth, 0L), aSize);
286 						const Rectangle aSrc(Point(0L, 0L), aSize);
287 						aBitmap.CopyPixel(aDst, aSrc);
288 
289 						const Size aSizeA(nWidth, nOffset);
290 						const Rectangle aDstA(Point(0L, 0L), aSizeA);
291 						const Rectangle aSrcA(Point(nWidth, nHeight - nOffset), aSizeA);
292 						aBitmap.CopyPixel(aDstA, aSrcA);
293 
294 						const Size aSizeB(nWidth, nHeight - nOffset);
295 						const Rectangle aDstB(Point(0L, nOffset), aSizeB);
296 						const Rectangle aSrcB(Point(nWidth, 0L), aSizeB);
297 						aBitmap.CopyPixel(aDstB, aSrcB);
298 					}
299 				}
300 			}
301 
302 			// init values with defaults
303 			basegfx::B2DPoint aBitmapSize(1.0, 1.0);
304 			basegfx::B2DVector aBitmapTopLeft(0.0, 0.0);
305 
306 			// are canges needed?
307 			if(getTiling() || !getStretch())
308 			{
309 				// init values with range sizes
310 				const double fRangeWidth(0.0 != rRange.getWidth() ? rRange.getWidth() : 1.0);
311 				const double fRangeHeight(0.0 != rRange.getHeight() ? rRange.getHeight() : 1.0);
312 				aBitmapSize = basegfx::B2DPoint(fRangeWidth, fRangeHeight);
313 
314 				// size changes
315 				if(0.0 != getSize().getX())
316 				{
317 					if(getSize().getX() < 0.0)
318 					{
319 						aBitmapSize.setX(aBitmapSize.getX() * (getSize().getX() * -0.01));
320 					}
321 					else
322 					{
323 						aBitmapSize.setX(getSize().getX());
324 					}
325 				}
326 				else
327 				{
328 					aBitmapSize.setX(aLogicalSize.getX());
329 				}
330 
331 				if(0.0 != getSize().getY())
332 				{
333 					if(getSize().getY() < 0.0)
334 					{
335 						aBitmapSize.setY(aBitmapSize.getY() * (getSize().getY() * -0.01));
336 					}
337 					else
338 					{
339 						aBitmapSize.setY(getSize().getY());
340 					}
341 				}
342 				else
343 				{
344 					aBitmapSize.setY(aLogicalSize.getY());
345 				}
346 
347 				// get values, force to centered if necessary
348 				const basegfx::B2DVector aRectPoint(getTiling() ? getRectPoint() : basegfx::B2DVector(0.0, 0.0));
349 
350 				// position changes X
351 				if(0.0 == aRectPoint.getX())
352 				{
353 					aBitmapTopLeft.setX((fRangeWidth - aBitmapSize.getX()) * 0.5);
354 				}
355 				else if(1.0 == aRectPoint.getX())
356 				{
357 					aBitmapTopLeft.setX(fRangeWidth - aBitmapSize.getX());
358 				}
359 
360 				if(getTiling() && 0.0 != getOffsetPosition().getX())
361 				{
362 					aBitmapTopLeft.setX(aBitmapTopLeft.getX() + (aBitmapSize.getX() * (getOffsetPosition().getX() * 0.01)));
363 				}
364 
365 				// position changes Y
366 				if(0.0 == aRectPoint.getY())
367 				{
368 					aBitmapTopLeft.setY((fRangeHeight - aBitmapSize.getY()) * 0.5);
369 				}
370 				else if(1.0 == aRectPoint.getY())
371 				{
372 					aBitmapTopLeft.setY(fRangeHeight - aBitmapSize.getY());
373 				}
374 
375 				if(getTiling() && 0.0 != getOffsetPosition().getY())
376 				{
377 					aBitmapTopLeft.setY(aBitmapTopLeft.getY() + (aBitmapSize.getY() * (getOffsetPosition().getY() * 0.01)));
378 				}
379 
380 				// apply expand
381 				if(bExpandWidth)
382 				{
383 					aBitmapSize.setX(aBitmapSize.getX() * 2.0);
384 				}
385 
386 				if(bExpandHeight)
387 				{
388 					aBitmapSize.setY(aBitmapSize.getY() * 2.0);
389 				}
390 
391 				// apply bitmap size scaling to unit rectangle
392 				aBitmapTopLeft.setX(aBitmapTopLeft.getX() / fRangeWidth);
393 				aBitmapTopLeft.setY(aBitmapTopLeft.getY() / fRangeHeight);
394 				aBitmapSize.setX(aBitmapSize.getX() / fRangeWidth);
395 				aBitmapSize.setY(aBitmapSize.getY() / fRangeHeight);
396 			}
397 
398 			return FillBitmapAttribute(BitmapEx(aBitmap), aBitmapTopLeft, aBitmapSize, getTiling());
399 		}
400 	} // end of namespace attribute
401 } // end of namespace drawinglayer
402 
403 //////////////////////////////////////////////////////////////////////////////
404 // eof
405