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