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