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/primitive2d/wallpaperprimitive2d.hxx>
28 #include <drawinglayer/primitive2d/bitmapprimitive2d.hxx>
29 #include <drawinglayer/primitive2d/drawinglayer_primitivetypes2d.hxx>
30 #include <drawinglayer/primitive2d/fillbitmapprimitive2d.hxx>
31 #include <basegfx/polygon/b2dpolygontools.hxx>
32 #include <basegfx/polygon/b2dpolygon.hxx>
33 #include <drawinglayer/primitive2d/maskprimitive2d.hxx>
34 
35 //////////////////////////////////////////////////////////////////////////////
36 
37 namespace drawinglayer
38 {
39 	namespace primitive2d
40 	{
41 		Primitive2DSequence WallpaperBitmapPrimitive2D::create2DDecomposition(const geometry::ViewInformation2D& /*rViewInformation*/) const
42 		{
43 			Primitive2DSequence aRetval;
44 
45 			if(!getLocalObjectRange().isEmpty() && !getBitmapEx().IsEmpty())
46 			{
47 				// get bitmap PIXEL size
48 			    const Size& rPixelSize = getBitmapEx().GetSizePixel();
49 
50 				if(rPixelSize.Width() > 0 && rPixelSize.Height() > 0)
51 				{
52 					if(WALLPAPER_SCALE == getWallpaperStyle())
53 					{
54 						// shortcut for scale; use simple BitmapPrimitive2D
55 						basegfx::B2DHomMatrix aObjectTransform;
56 
57 						aObjectTransform.set(0, 0, getLocalObjectRange().getWidth());
58 						aObjectTransform.set(1, 1, getLocalObjectRange().getHeight());
59 						aObjectTransform.set(0, 2, getLocalObjectRange().getMinX());
60 						aObjectTransform.set(1, 2, getLocalObjectRange().getMinY());
61 
62 						Primitive2DReference xReference(
63 							new BitmapPrimitive2D(
64 								getBitmapEx(),
65 								aObjectTransform));
66 
67 						aRetval = Primitive2DSequence(&xReference, 1);
68 					}
69 					else
70 					{
71 						// transform to logic size
72 						basegfx::B2DHomMatrix aInverseViewTransformation(getViewTransformation());
73 						aInverseViewTransformation.invert();
74 						basegfx::B2DVector aLogicSize(rPixelSize.Width(), rPixelSize.Height());
75 						aLogicSize = aInverseViewTransformation * aLogicSize;
76 
77 						// apply laout
78 						basegfx::B2DPoint aTargetTopLeft(getLocalObjectRange().getMinimum());
79 						bool bUseTargetTopLeft(true);
80 						bool bNeedsClipping(false);
81 
82 						switch(getWallpaperStyle())
83 						{
84 							default: //case WALLPAPER_TILE :, also WALLPAPER_NULL and WALLPAPER_APPLICATIONGRADIENT
85 							{
86 								bUseTargetTopLeft = false;
87 								break;
88 							}
89 							case WALLPAPER_SCALE :
90 							{
91 								// handled by shortcut above
92 								break;
93 							}
94 							case WALLPAPER_TOPLEFT :
95 							{
96 								// nothing to do
97 								break;
98 							}
99 							case WALLPAPER_TOP :
100 							{
101 								const basegfx::B2DPoint aCenter(getLocalObjectRange().getCenter());
102 								aTargetTopLeft.setX(aCenter.getX() - (aLogicSize.getX() * 0.5));
103 								break;
104 							}
105 							case WALLPAPER_TOPRIGHT :
106 							{
107 								aTargetTopLeft.setX(getLocalObjectRange().getMaxX() - aLogicSize.getX());
108 								break;
109 							}
110 							case WALLPAPER_LEFT :
111 							{
112 								const basegfx::B2DPoint aCenter(getLocalObjectRange().getCenter());
113 								aTargetTopLeft.setY(aCenter.getY() - (aLogicSize.getY() * 0.5));
114 								break;
115 							}
116 							case WALLPAPER_CENTER :
117 							{
118 								const basegfx::B2DPoint aCenter(getLocalObjectRange().getCenter());
119 								aTargetTopLeft = aCenter - (aLogicSize * 0.5);
120 								break;
121 							}
122 							case WALLPAPER_RIGHT :
123 							{
124 								const basegfx::B2DPoint aCenter(getLocalObjectRange().getCenter());
125 								aTargetTopLeft.setX(getLocalObjectRange().getMaxX() - aLogicSize.getX());
126 								aTargetTopLeft.setY(aCenter.getY() - (aLogicSize.getY() * 0.5));
127 								break;
128 							}
129 							case WALLPAPER_BOTTOMLEFT :
130 							{
131 								aTargetTopLeft.setY(getLocalObjectRange().getMaxY() - aLogicSize.getY());
132 								break;
133 							}
134 							case WALLPAPER_BOTTOM :
135 							{
136 								const basegfx::B2DPoint aCenter(getLocalObjectRange().getCenter());
137 								aTargetTopLeft.setX(aCenter.getX() - (aLogicSize.getX() * 0.5));
138 								aTargetTopLeft.setY(getLocalObjectRange().getMaxY() - aLogicSize.getY());
139 								break;
140 							}
141 							case WALLPAPER_BOTTOMRIGHT :
142 							{
143 								aTargetTopLeft = getLocalObjectRange().getMaximum() - aLogicSize;
144 								break;
145 							}
146 						}
147 
148 						if(bUseTargetTopLeft)
149 						{
150 							// fill target range
151 							const basegfx::B2DRange aTargetRange(aTargetTopLeft, aTargetTopLeft + aLogicSize);
152 
153 							// create aligned, single BitmapPrimitive2D
154 							basegfx::B2DHomMatrix aObjectTransform;
155 
156 							aObjectTransform.set(0, 0, aTargetRange.getWidth());
157 							aObjectTransform.set(1, 1, aTargetRange.getHeight());
158 							aObjectTransform.set(0, 2, aTargetRange.getMinX());
159 							aObjectTransform.set(1, 2, aTargetRange.getMinY());
160 
161 							Primitive2DReference xReference(
162 								new BitmapPrimitive2D(
163 									getBitmapEx(),
164 									aObjectTransform));
165 							aRetval = Primitive2DSequence(&xReference, 1);
166 
167 							// clip when not completely inside object range
168 							bNeedsClipping = !getLocalObjectRange().isInside(aTargetRange);
169 						}
170 						else
171 						{
172 							// WALLPAPER_TILE, WALLPAPER_NULL, WALLPAPER_APPLICATIONGRADIENT
173 							// convert to relative positions
174 							const basegfx::B2DVector aRelativeSize(
175 								aLogicSize.getX() / (getLocalObjectRange().getWidth() ? getLocalObjectRange().getWidth() : 1.0),
176 								aLogicSize.getY() / (getLocalObjectRange().getHeight() ? getLocalObjectRange().getHeight() : 1.0));
177 							basegfx::B2DPoint aRelativeTopLeft(0.0, 0.0);
178 
179 							if(WALLPAPER_TILE != getWallpaperStyle())
180 							{
181 								aRelativeTopLeft.setX(0.5 - aRelativeSize.getX());
182 								aRelativeTopLeft.setY(0.5 - aRelativeSize.getY());
183 							}
184 
185 							// prepare FillBitmapAttribute
186 							const attribute::FillBitmapAttribute aFillBitmapAttribute(
187 								getBitmapEx(),
188 								aRelativeTopLeft,
189 								aRelativeSize,
190 								true);
191 
192 							// create ObjectTransform
193 							basegfx::B2DHomMatrix aObjectTransform;
194 
195 							aObjectTransform.set(0, 0, getLocalObjectRange().getWidth());
196 							aObjectTransform.set(1, 1, getLocalObjectRange().getHeight());
197 							aObjectTransform.set(0, 2, getLocalObjectRange().getMinX());
198 							aObjectTransform.set(1, 2, getLocalObjectRange().getMinY());
199 
200 							// create FillBitmapPrimitive
201 							const drawinglayer::primitive2d::Primitive2DReference xFillBitmap(
202 								new drawinglayer::primitive2d::FillBitmapPrimitive2D(
203 									aObjectTransform,
204 									aFillBitmapAttribute));
205 							aRetval = Primitive2DSequence(&xFillBitmap, 1);
206 
207 							// always embed tiled fill to clipping
208 							bNeedsClipping = true;
209 						}
210 
211 						if(bNeedsClipping)
212 						{
213 							// embed to clipping; this is necessary for tiled fills
214 							const basegfx::B2DPolyPolygon aPolyPolygon(
215                                 basegfx::tools::createPolygonFromRect(getLocalObjectRange()));
216 							const drawinglayer::primitive2d::Primitive2DReference xClippedFill(
217 								new drawinglayer::primitive2d::MaskPrimitive2D(
218 									aPolyPolygon,
219 									aRetval));
220 							aRetval = Primitive2DSequence(&xClippedFill, 1);
221 						}
222 					}
223 				}
224 			}
225 
226 			return aRetval;
227 		}
228 
229 		WallpaperBitmapPrimitive2D::WallpaperBitmapPrimitive2D(
230 			const basegfx::B2DRange& rObjectRange,
231 			const BitmapEx& rBitmapEx,
232 			WallpaperStyle eWallpaperStyle)
233 		:	ViewTransformationDependentPrimitive2D(),
234 			maObjectRange(rObjectRange),
235 			maBitmapEx(rBitmapEx),
236 			meWallpaperStyle(eWallpaperStyle)
237 		{
238 		}
239 
240 		bool WallpaperBitmapPrimitive2D::operator==(const BasePrimitive2D& rPrimitive) const
241 		{
242 			if(ViewTransformationDependentPrimitive2D::operator==(rPrimitive))
243 			{
244 				const WallpaperBitmapPrimitive2D& rCompare = (WallpaperBitmapPrimitive2D&)rPrimitive;
245 
246 				return (getLocalObjectRange() == rCompare.getLocalObjectRange()
247 					&& getBitmapEx() == rCompare.getBitmapEx()
248 					&& getWallpaperStyle() == rCompare.getWallpaperStyle());
249 			}
250 
251 			return false;
252 		}
253 
254 		basegfx::B2DRange WallpaperBitmapPrimitive2D::getB2DRange(const geometry::ViewInformation2D& /*rViewInformation*/) const
255 		{
256 			return getLocalObjectRange();
257 		}
258 
259 		// provide unique ID
260 		ImplPrimitrive2DIDBlock(WallpaperBitmapPrimitive2D, PRIMITIVE2D_ID_WALLPAPERBITMAPPRIMITIVE2D)
261 	} // end of namespace primitive2d
262 } // end of namespace drawinglayer
263 
264 //////////////////////////////////////////////////////////////////////////////
265 // eof
266