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/attribute/sdrfillgraphicattribute.hxx>
28 #include <drawinglayer/attribute/fillgraphicattribute.hxx>
29 #include <vcl/graph.hxx>
30 
31 //////////////////////////////////////////////////////////////////////////////
32 
33 namespace drawinglayer
34 {
35 	namespace attribute
36 	{
37 		class ImpSdrFillGraphicAttribute
38 		{
39         public:
40 		    // refcounter
41 		    sal_uInt32								mnRefCount;
42 
43             // data definitions
44 			Graphic                                 maFillGraphic;
45             basegfx::B2DVector                      maGraphicLogicSize;
46 			basegfx::B2DVector						maSize;
47 			basegfx::B2DVector						maOffset;
48 			basegfx::B2DVector						maOffsetPosition;
49 			basegfx::B2DVector						maRectPoint;
50 
51 			// bitfield
52 			unsigned								mbTiling : 1;
53 			unsigned								mbStretch : 1;
54 			unsigned								mbLogSize : 1;
55 
56 			ImpSdrFillGraphicAttribute(
57 				const Graphic& rFillGraphic,
58                 const basegfx::B2DVector& rGraphicLogicSize,
59                 const basegfx::B2DVector& rSize,
60                 const basegfx::B2DVector& rOffset,
61 				const basegfx::B2DVector& rOffsetPosition,
62                 const basegfx::B2DVector& rRectPoint,
63 				bool bTiling,
64                 bool bStretch,
65                 bool bLogSize)
66 		    :	mnRefCount(0),
67 		    	maFillGraphic(rFillGraphic),
68                 maGraphicLogicSize(rGraphicLogicSize),
69 			    maSize(rSize),
70 			    maOffset(rOffset),
71 			    maOffsetPosition(rOffsetPosition),
72 			    maRectPoint(rRectPoint),
73 			    mbTiling(bTiling),
74 			    mbStretch(bStretch),
75 			    mbLogSize(bLogSize)
76 		    {
77 		    }
78 
79 			// data read access
80             const Graphic& getFillGraphic() const { return maFillGraphic; }
81             const basegfx::B2DVector& getGraphicLogicSize() const { return maGraphicLogicSize; }
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 ImpSdrFillGraphicAttribute& rCandidate) const
91             {
92 			    return (getFillGraphic() == rCandidate.getFillGraphic()
93                     && getGraphicLogicSize() == rCandidate.getGraphicLogicSize()
94 				    && getSize() == rCandidate.getSize()
95 				    && getOffset() == rCandidate.getOffset()
96 				    && getOffsetPosition() == rCandidate.getOffsetPosition()
97 				    && getRectPoint() == rCandidate.getRectPoint()
98 				    && getTiling() == rCandidate.getTiling()
99 				    && getStretch() == rCandidate.getStretch()
100 				    && getLogSize() == rCandidate.getLogSize());
101             }
102 
103             static ImpSdrFillGraphicAttribute* get_global_default()
104             {
105                 static ImpSdrFillGraphicAttribute* pDefault = 0;
106 
107                 if(!pDefault)
108                 {
109                     pDefault = new ImpSdrFillGraphicAttribute(
110 			            Graphic(),
111                         basegfx::B2DVector(),
112                         basegfx::B2DVector(),
113                         basegfx::B2DVector(),
114 			            basegfx::B2DVector(),
115                         basegfx::B2DVector(),
116 			            false,
117                         false,
118                         false);
119 
120                     // never delete; start with RefCount 1, not 0
121     			    pDefault->mnRefCount++;
122                 }
123 
124                 return pDefault;
125             }
126 		};
127 
128         SdrFillGraphicAttribute::SdrFillGraphicAttribute(
129 			const Graphic& rFillGraphic,
130             const basegfx::B2DVector& rGraphicLogicSize,
131             const basegfx::B2DVector& rSize,
132             const basegfx::B2DVector& rOffset,
133 			const basegfx::B2DVector& rOffsetPosition,
134             const basegfx::B2DVector& rRectPoint,
135 			bool bTiling,
136             bool bStretch,
137             bool bLogSize)
138 		:	mpSdrFillGraphicAttribute(
139                 new ImpSdrFillGraphicAttribute(
140                     rFillGraphic,
141                     rGraphicLogicSize,
142                     rSize,
143                     rOffset,
144                     rOffsetPosition,
145                     rRectPoint,
146                     bTiling,
147                     bStretch,
148                     bLogSize))
149 		{
150 		}
151 
152 		SdrFillGraphicAttribute::SdrFillGraphicAttribute()
153         :	mpSdrFillGraphicAttribute(ImpSdrFillGraphicAttribute::get_global_default())
154 		{
155 			mpSdrFillGraphicAttribute->mnRefCount++;
156 		}
157 
158         SdrFillGraphicAttribute::SdrFillGraphicAttribute(const SdrFillGraphicAttribute& rCandidate)
159 		:	mpSdrFillGraphicAttribute(rCandidate.mpSdrFillGraphicAttribute)
160 		{
161 			mpSdrFillGraphicAttribute->mnRefCount++;
162 		}
163 
164 		SdrFillGraphicAttribute::~SdrFillGraphicAttribute()
165 		{
166 			if(mpSdrFillGraphicAttribute->mnRefCount)
167 			{
168 				mpSdrFillGraphicAttribute->mnRefCount--;
169 			}
170 			else
171 			{
172 				delete mpSdrFillGraphicAttribute;
173 			}
174 		}
175 
176         bool SdrFillGraphicAttribute::isDefault() const
177         {
178             return mpSdrFillGraphicAttribute == ImpSdrFillGraphicAttribute::get_global_default();
179         }
180 
181         SdrFillGraphicAttribute& SdrFillGraphicAttribute::operator=(const SdrFillGraphicAttribute& rCandidate)
182 		{
183 			if(rCandidate.mpSdrFillGraphicAttribute != mpSdrFillGraphicAttribute)
184 			{
185 				if(mpSdrFillGraphicAttribute->mnRefCount)
186 				{
187 					mpSdrFillGraphicAttribute->mnRefCount--;
188 				}
189 				else
190 				{
191 					delete mpSdrFillGraphicAttribute;
192 				}
193 
194 				mpSdrFillGraphicAttribute = rCandidate.mpSdrFillGraphicAttribute;
195 				mpSdrFillGraphicAttribute->mnRefCount++;
196 			}
197 
198 			return *this;
199 		}
200 
201 		bool SdrFillGraphicAttribute::operator==(const SdrFillGraphicAttribute& rCandidate) const
202 		{
203 			if(rCandidate.mpSdrFillGraphicAttribute == mpSdrFillGraphicAttribute)
204 			{
205 				return true;
206 			}
207 
208 			if(rCandidate.isDefault() != isDefault())
209 			{
210 				return false;
211 			}
212 
213 			return (*rCandidate.mpSdrFillGraphicAttribute == *mpSdrFillGraphicAttribute);
214 		}
215 
216         const Graphic& SdrFillGraphicAttribute::getFillGraphic() const
217         {
218             return mpSdrFillGraphicAttribute->getFillGraphic();
219         }
220 
221         const basegfx::B2DVector& SdrFillGraphicAttribute::getGraphicLogicSize() const
222         {
223             return mpSdrFillGraphicAttribute->getGraphicLogicSize();
224         }
225 
226         const basegfx::B2DVector& SdrFillGraphicAttribute::getSize() const
227         {
228             return mpSdrFillGraphicAttribute->getSize();
229         }
230 
231         const basegfx::B2DVector& SdrFillGraphicAttribute::getOffset() const
232         {
233             return mpSdrFillGraphicAttribute->getOffset();
234         }
235 
236         const basegfx::B2DVector& SdrFillGraphicAttribute::getOffsetPosition() const
237         {
238             return mpSdrFillGraphicAttribute->getOffsetPosition();
239         }
240 
241         const basegfx::B2DVector& SdrFillGraphicAttribute::getRectPoint() const
242         {
243             return mpSdrFillGraphicAttribute->getRectPoint();
244         }
245 
246         bool SdrFillGraphicAttribute::getTiling() const
247         {
248             return mpSdrFillGraphicAttribute->getTiling();
249         }
250 
251         bool SdrFillGraphicAttribute::getStretch() const
252         {
253             return mpSdrFillGraphicAttribute->getStretch();
254         }
255 
256         bool SdrFillGraphicAttribute::getLogSize() const
257         {
258             return mpSdrFillGraphicAttribute->getLogSize();
259         }
260 
261         FillGraphicAttribute SdrFillGraphicAttribute::createFillGraphicAttribute(const basegfx::B2DRange& rRange) const
262 		{
263 			// get logical size of bitmap (before expanding eventually)
264 			Graphic aGraphic(getFillGraphic());
265 
266 			// init values with defaults
267 			basegfx::B2DPoint aBitmapSize(1.0, 1.0);
268 			basegfx::B2DVector aBitmapTopLeft(0.0, 0.0);
269 
270 			// are changes needed?
271 			if(getTiling() || !getStretch())
272 			{
273 				// init values with range sizes
274 				const double fRangeWidth(0.0 != rRange.getWidth() ? rRange.getWidth() : 1.0);
275 				const double fRangeHeight(0.0 != rRange.getHeight() ? rRange.getHeight() : 1.0);
276 				aBitmapSize = basegfx::B2DPoint(fRangeWidth, fRangeHeight);
277 
278 				// size changes
279 				if(0.0 != getSize().getX())
280 				{
281 					if(getSize().getX() < 0.0)
282 					{
283 						aBitmapSize.setX(aBitmapSize.getX() * (getSize().getX() * -0.01));
284 					}
285 					else
286 					{
287 						aBitmapSize.setX(getSize().getX());
288 					}
289 				}
290 				else
291 				{
292                     // #124002# use GraphicLogicSize directly, do not try to use GetPrefSize
293                     // of the graphic, that may not be adapted to the MapMode of the target
294                     aBitmapSize.setX(getGraphicLogicSize().getX());
295 				}
296 
297 				if(0.0 != getSize().getY())
298 				{
299 					if(getSize().getY() < 0.0)
300 					{
301 						aBitmapSize.setY(aBitmapSize.getY() * (getSize().getY() * -0.01));
302 					}
303 					else
304 					{
305 						aBitmapSize.setY(getSize().getY());
306 					}
307 				}
308 				else
309 				{
310                     // #124002# use GraphicLogicSize directly, do not try to use GetPrefSize
311                     // of the graphic, that may not be adapted to the MapMode of the target
312                     aBitmapSize.setY(getGraphicLogicSize().getY());
313 				}
314 
315 				// get values, force to centered if necessary
316 				const basegfx::B2DVector aRectPoint(getTiling() ? getRectPoint() : basegfx::B2DVector(0.0, 0.0));
317 
318 				// position changes X
319 				if(0.0 == aRectPoint.getX())
320 				{
321 					aBitmapTopLeft.setX((fRangeWidth - aBitmapSize.getX()) * 0.5);
322 				}
323 				else if(1.0 == aRectPoint.getX())
324 				{
325 					aBitmapTopLeft.setX(fRangeWidth - aBitmapSize.getX());
326 				}
327 
328 				if(getTiling() && 0.0 != getOffsetPosition().getX())
329 				{
330 					aBitmapTopLeft.setX(aBitmapTopLeft.getX() + (aBitmapSize.getX() * (getOffsetPosition().getX() * 0.01)));
331 				}
332 
333 				// position changes Y
334 				if(0.0 == aRectPoint.getY())
335 				{
336 					aBitmapTopLeft.setY((fRangeHeight - aBitmapSize.getY()) * 0.5);
337 				}
338 				else if(1.0 == aRectPoint.getY())
339 				{
340 					aBitmapTopLeft.setY(fRangeHeight - aBitmapSize.getY());
341 				}
342 
343 				if(getTiling() && 0.0 != getOffsetPosition().getY())
344 				{
345 					aBitmapTopLeft.setY(aBitmapTopLeft.getY() + (aBitmapSize.getY() * (getOffsetPosition().getY() * 0.01)));
346 				}
347 
348 				// apply bitmap size scaling to unit rectangle
349 				aBitmapTopLeft.setX(aBitmapTopLeft.getX() / fRangeWidth);
350 				aBitmapTopLeft.setY(aBitmapTopLeft.getY() / fRangeHeight);
351 				aBitmapSize.setX(aBitmapSize.getX() / fRangeWidth);
352 				aBitmapSize.setY(aBitmapSize.getY() / fRangeHeight);
353 			}
354 
355             // get offset in percent
356             const double fOffsetX(basegfx::clamp(getOffset().getX() * 0.01, 0.0, 1.0));
357             const double fOffsetY(basegfx::clamp(getOffset().getY() * 0.01, 0.0, 1.0));
358 
359             // create FillGraphicAttribute
360             return FillGraphicAttribute(
361                 aGraphic,
362                 basegfx::B2DRange(aBitmapTopLeft, aBitmapTopLeft + aBitmapSize),
363                 getTiling(),
364                 fOffsetX,
365                 fOffsetY);
366 		}
367 	} // end of namespace attribute
368 } // end of namespace drawinglayer
369 
370 //////////////////////////////////////////////////////////////////////////////
371 // eof
372