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/pagepreviewprimitive2d.hxx>
32 #include <drawinglayer/primitive2d/drawinglayer_primitivetypes2d.hxx>
33 #include <drawinglayer/primitive2d/maskprimitive2d.hxx>
34 #include <basegfx/polygon/b2dpolygontools.hxx>
35 #include <basegfx/polygon/b2dpolygon.hxx>
36 #include <drawinglayer/primitive2d/transformprimitive2d.hxx>
37 #include <basegfx/matrix/b2dhommatrixtools.hxx>
38 
39 //////////////////////////////////////////////////////////////////////////////
40 
41 using namespace com::sun::star;
42 
43 //////////////////////////////////////////////////////////////////////////////
44 
45 namespace drawinglayer
46 {
47 	namespace primitive2d
48 	{
49 		Primitive2DSequence PagePreviewPrimitive2D::create2DDecomposition(const geometry::ViewInformation2D& rViewInformation) const
50         {
51     		Primitive2DSequence xRetval;
52             Primitive2DSequence aContent(getPageContent());
53 
54             if(aContent.hasElements()
55 				&& basegfx::fTools::more(getContentWidth(), 0.0)
56 				&& basegfx::fTools::more(getContentHeight(), 0.0))
57             {
58 				// the decomposed matrix will be needed
59 				basegfx::B2DVector aScale, aTranslate;
60 				double fRotate, fShearX;
61 				getTransform().decompose(aScale, aTranslate, fRotate, fShearX);
62 
63 				if(basegfx::fTools::more(aScale.getX(), 0.0) && basegfx::fTools::more(aScale.getY(), 0.0))
64 				{
65 					// check if content overlaps with tageted size and needs to be embedded with a
66 					// clipping primitive
67 					const basegfx::B2DRange aRealContentRange(getB2DRangeFromPrimitive2DSequence(aContent, rViewInformation));
68 					const basegfx::B2DRange aAllowedContentRange(0.0, 0.0, getContentWidth(), getContentHeight());
69 
70 					if(!aAllowedContentRange.isInside(aRealContentRange))
71 					{
72 						const Primitive2DReference xReferenceA(
73                             new MaskPrimitive2D(
74                                 basegfx::B2DPolyPolygon(
75                                     basegfx::tools::createPolygonFromRect(aAllowedContentRange)), aContent));
76 						aContent = Primitive2DSequence(&xReferenceA, 1);
77 					}
78 
79 					// create a mapping from content to object.
80 					basegfx::B2DHomMatrix aPageTrans;
81 
82 					if(getKeepAspectRatio())
83 					{
84 					    // #i101075# when keeping the aspect ratio is wanted, it is necessary to calculate
85                         // an equidistant scaling in X and Y and a corresponding translation to
86                         // center the output. Calculate needed scale factors
87 					    const double fScaleX(aScale.getX() / getContentWidth());
88 					    const double fScaleY(aScale.getY() / getContentHeight());
89 
90                         // to keep the aspect, use the smaller scale and adapt missing size by translation
91 						if(fScaleX < fScaleY)
92 						{
93 							// height needs to be adapted
94 							const double fNeededHeight(aScale.getY() / fScaleX);
95 							const double fSpaceToAdd(fNeededHeight - getContentHeight());
96 
97 							aPageTrans.translate(0.0, fSpaceToAdd * 0.5);
98 							aPageTrans.scale(fScaleX, aScale.getY() / fNeededHeight);
99 						}
100 						else
101 						{
102 							// width needs to be adapted
103 							const double fNeededWidth(aScale.getX() / fScaleY);
104 							const double fSpaceToAdd(fNeededWidth - getContentWidth());
105 
106 							aPageTrans.translate(fSpaceToAdd * 0.5, 0.0);
107 							aPageTrans.scale(aScale.getX() / fNeededWidth, fScaleY);
108 						}
109 
110                         // add the missing object transformation aspects
111 						const basegfx::B2DHomMatrix aCombined(basegfx::tools::createShearXRotateTranslateB2DHomMatrix(
112 							fShearX, fRotate, aTranslate.getX(), aTranslate.getY()));
113 					    aPageTrans = aCombined * aPageTrans;
114 					}
115 					else
116 					{
117                         // completely scale to PageObject size. Scale to unit size.
118 						aPageTrans.scale(1.0/ getContentWidth(), 1.0 / getContentHeight());
119 
120                         // apply object matrix
121 						aPageTrans *= getTransform();
122 					}
123 
124 					// embed in necessary transformation to map from SdrPage to SdrPageObject
125 					const Primitive2DReference xReferenceB(new TransformPrimitive2D(aPageTrans, aContent));
126 					xRetval = Primitive2DSequence(&xReferenceB, 1);
127 				}
128             }
129 
130             return xRetval;
131         }
132 
133 		PagePreviewPrimitive2D::PagePreviewPrimitive2D(
134 			const ::com::sun::star::uno::Reference< ::com::sun::star::drawing::XDrawPage >& rxDrawPage,
135             const basegfx::B2DHomMatrix& rTransform,
136             double fContentWidth,
137             double fContentHeight,
138 			const Primitive2DSequence& rPageContent,
139 			bool bKeepAspectRatio)
140 		:	BufferedDecompositionPrimitive2D(),
141             mxDrawPage(rxDrawPage),
142             maPageContent(rPageContent),
143             maTransform(rTransform),
144             mfContentWidth(fContentWidth),
145             mfContentHeight(fContentHeight),
146 			mbKeepAspectRatio(bKeepAspectRatio)
147 		{
148 		}
149 
150 		bool PagePreviewPrimitive2D::operator==(const BasePrimitive2D& rPrimitive) const
151 		{
152 			if(BasePrimitive2D::operator==(rPrimitive))
153 			{
154 				const PagePreviewPrimitive2D& rCompare = static_cast< const PagePreviewPrimitive2D& >(rPrimitive);
155 
156                 return (getXDrawPage() == rCompare.getXDrawPage()
157                     && getPageContent() == rCompare.getPageContent()
158                     && getTransform() == rCompare.getTransform()
159                     && getContentWidth() == rCompare.getContentWidth()
160                     && getContentHeight() == rCompare.getContentHeight()
161                     && getKeepAspectRatio() == rCompare.getKeepAspectRatio());
162 			}
163 
164 			return false;
165 		}
166 
167         basegfx::B2DRange PagePreviewPrimitive2D::getB2DRange(const geometry::ViewInformation2D& /*rViewInformation`*/) const
168         {
169             // nothing is allowed to stick out of a PagePreviewPrimitive, thus we
170             // can quickly deliver our range here
171 			basegfx::B2DRange aRetval(0.0, 0.0, 1.0, 1.0);
172 			aRetval.transform(getTransform());
173 			return aRetval;
174         }
175 
176 		// provide unique ID
177 		ImplPrimitrive2DIDBlock(PagePreviewPrimitive2D, PRIMITIVE2D_ID_PAGEPREVIEWPRIMITIVE2D)
178 
179 	} // end of namespace primitive2d
180 } // end of namespace drawinglayer
181 
182 //////////////////////////////////////////////////////////////////////////////
183 // eof
184