1*464702f4SAndrew Rist /**************************************************************
2cdf0e10cSrcweir  *
3*464702f4SAndrew Rist  * Licensed to the Apache Software Foundation (ASF) under one
4*464702f4SAndrew Rist  * or more contributor license agreements.  See the NOTICE file
5*464702f4SAndrew Rist  * distributed with this work for additional information
6*464702f4SAndrew Rist  * regarding copyright ownership.  The ASF licenses this file
7*464702f4SAndrew Rist  * to you under the Apache License, Version 2.0 (the
8*464702f4SAndrew Rist  * "License"); you may not use this file except in compliance
9*464702f4SAndrew Rist  * with the License.  You may obtain a copy of the License at
10*464702f4SAndrew Rist  *
11*464702f4SAndrew Rist  *   http://www.apache.org/licenses/LICENSE-2.0
12*464702f4SAndrew Rist  *
13*464702f4SAndrew Rist  * Unless required by applicable law or agreed to in writing,
14*464702f4SAndrew Rist  * software distributed under the License is distributed on an
15*464702f4SAndrew Rist  * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
16*464702f4SAndrew Rist  * KIND, either express or implied.  See the License for the
17*464702f4SAndrew Rist  * specific language governing permissions and limitations
18*464702f4SAndrew Rist  * under the License.
19*464702f4SAndrew Rist  *
20*464702f4SAndrew Rist  *************************************************************/
21*464702f4SAndrew Rist 
22*464702f4SAndrew Rist 
23cdf0e10cSrcweir 
24cdf0e10cSrcweir // MARKER(update_precomp.py): autogen include statement, do not remove
25cdf0e10cSrcweir #include "precompiled_drawinglayer.hxx"
26cdf0e10cSrcweir 
27cdf0e10cSrcweir #include <drawinglayer/primitive2d/controlprimitive2d.hxx>
28cdf0e10cSrcweir #include <com/sun/star/beans/XPropertySet.hpp>
29cdf0e10cSrcweir #include <comphelper/processfactory.hxx>
30cdf0e10cSrcweir #include <com/sun/star/awt/XWindow2.hpp>
31cdf0e10cSrcweir #include <drawinglayer/geometry/viewinformation2d.hxx>
32cdf0e10cSrcweir #include <vcl/virdev.hxx>
33cdf0e10cSrcweir #include <vcl/svapp.hxx>
34cdf0e10cSrcweir #include <com/sun/star/awt/PosSize.hpp>
35cdf0e10cSrcweir #include <vcl/bitmapex.hxx>
36cdf0e10cSrcweir #include <drawinglayer/primitive2d/bitmapprimitive2d.hxx>
37cdf0e10cSrcweir #include <tools/diagnose_ex.h>
38cdf0e10cSrcweir #include <basegfx/polygon/b2dpolygontools.hxx>
39cdf0e10cSrcweir #include <basegfx/polygon/b2dpolygon.hxx>
40cdf0e10cSrcweir #include <drawinglayer/primitive2d/polygonprimitive2d.hxx>
41cdf0e10cSrcweir #include <drawinglayer/primitive2d/drawinglayer_primitivetypes2d.hxx>
42cdf0e10cSrcweir #include <svtools/optionsdrawinglayer.hxx>
43cdf0e10cSrcweir #include <toolkit/awt/vclxwindow.hxx>
44cdf0e10cSrcweir #include <vcl/window.hxx>
45cdf0e10cSrcweir #include <basegfx/matrix/b2dhommatrixtools.hxx>
46cdf0e10cSrcweir 
47cdf0e10cSrcweir //////////////////////////////////////////////////////////////////////////////
48cdf0e10cSrcweir 
49cdf0e10cSrcweir using namespace com::sun::star;
50cdf0e10cSrcweir 
51cdf0e10cSrcweir //////////////////////////////////////////////////////////////////////////////
52cdf0e10cSrcweir 
53cdf0e10cSrcweir namespace drawinglayer
54cdf0e10cSrcweir {
55cdf0e10cSrcweir 	namespace primitive2d
56cdf0e10cSrcweir 	{
createXControl()57cdf0e10cSrcweir 		void ControlPrimitive2D::createXControl()
58cdf0e10cSrcweir 		{
59cdf0e10cSrcweir 			if(!mxXControl.is() && getControlModel().is())
60cdf0e10cSrcweir 			{
61cdf0e10cSrcweir 				uno::Reference< beans::XPropertySet > xSet(getControlModel(), uno::UNO_QUERY);
62cdf0e10cSrcweir 
63cdf0e10cSrcweir 				if(xSet.is())
64cdf0e10cSrcweir 				{
65cdf0e10cSrcweir 					uno::Any aValue(xSet->getPropertyValue(rtl::OUString::createFromAscii("DefaultControl")));
66cdf0e10cSrcweir 					rtl::OUString aUnoControlTypeName;
67cdf0e10cSrcweir 
68cdf0e10cSrcweir 					if(aValue >>= aUnoControlTypeName)
69cdf0e10cSrcweir 					{
70cdf0e10cSrcweir 						if(aUnoControlTypeName.getLength())
71cdf0e10cSrcweir 						{
72cdf0e10cSrcweir 							uno::Reference< lang::XMultiServiceFactory > xFactory( comphelper::getProcessServiceFactory() );
73cdf0e10cSrcweir 
74cdf0e10cSrcweir 							if(xFactory.is())
75cdf0e10cSrcweir 							{
76cdf0e10cSrcweir 								uno::Reference< awt::XControl > xXControl(xFactory->createInstance(aUnoControlTypeName), uno::UNO_QUERY);
77cdf0e10cSrcweir 
78cdf0e10cSrcweir 								if(xXControl.is())
79cdf0e10cSrcweir 								{
80cdf0e10cSrcweir 									xXControl->setModel(getControlModel());
81cdf0e10cSrcweir 
82cdf0e10cSrcweir 									// remember XControl
83cdf0e10cSrcweir 									mxXControl = xXControl;
84cdf0e10cSrcweir 								}
85cdf0e10cSrcweir 							}
86cdf0e10cSrcweir 						}
87cdf0e10cSrcweir 					}
88cdf0e10cSrcweir 				}
89cdf0e10cSrcweir 			}
90cdf0e10cSrcweir 		}
91cdf0e10cSrcweir 
createBitmapDecomposition(const geometry::ViewInformation2D & rViewInformation) const92cdf0e10cSrcweir 		Primitive2DReference ControlPrimitive2D::createBitmapDecomposition(const geometry::ViewInformation2D& rViewInformation) const
93cdf0e10cSrcweir 		{
94cdf0e10cSrcweir 			Primitive2DReference xRetval;
95cdf0e10cSrcweir 			const uno::Reference< awt::XControl >& rXControl(getXControl());
96cdf0e10cSrcweir 
97cdf0e10cSrcweir 			if(rXControl.is())
98cdf0e10cSrcweir 			{
99cdf0e10cSrcweir 				uno::Reference< awt::XWindow > xControlWindow(rXControl, uno::UNO_QUERY);
100cdf0e10cSrcweir 
101cdf0e10cSrcweir 				if(xControlWindow.is())
102cdf0e10cSrcweir 				{
103cdf0e10cSrcweir 					// get decomposition to get size
104cdf0e10cSrcweir 					basegfx::B2DVector aScale, aTranslate;
105cdf0e10cSrcweir 					double fRotate, fShearX;
106cdf0e10cSrcweir 					getTransform().decompose(aScale, aTranslate, fRotate, fShearX);
107cdf0e10cSrcweir 
108cdf0e10cSrcweir 					// get absolute discrete size (no mirror or rotate here)
109cdf0e10cSrcweir 					aScale = basegfx::absolute(aScale);
110cdf0e10cSrcweir 					basegfx::B2DVector aDiscreteSize(rViewInformation.getObjectToViewTransformation() * aScale);
111cdf0e10cSrcweir 
112cdf0e10cSrcweir 					// limit to a maximum square size, e.g. 300x150 pixels (45000)
113cdf0e10cSrcweir                     const SvtOptionsDrawinglayer aDrawinglayerOpt;
114cdf0e10cSrcweir 					const double fDiscreteMax(aDrawinglayerOpt.GetQuadraticFormControlRenderLimit());
115cdf0e10cSrcweir 					const double fDiscreteQuadratic(aDiscreteSize.getX() * aDiscreteSize.getY());
116cdf0e10cSrcweir                     const bool bScaleUsed(fDiscreteQuadratic > fDiscreteMax);
117cdf0e10cSrcweir                     double fFactor(1.0);
118cdf0e10cSrcweir 
119cdf0e10cSrcweir 					if(bScaleUsed)
120cdf0e10cSrcweir 					{
121cdf0e10cSrcweir                         // get factor and adapt to scaled size
122cdf0e10cSrcweir 						fFactor = sqrt(fDiscreteMax / fDiscreteQuadratic);
123cdf0e10cSrcweir 						aDiscreteSize *= fFactor;
124cdf0e10cSrcweir 					}
125cdf0e10cSrcweir 
126cdf0e10cSrcweir 					// go to integer
127cdf0e10cSrcweir 					const sal_Int32 nSizeX(basegfx::fround(aDiscreteSize.getX()));
128cdf0e10cSrcweir 					const sal_Int32 nSizeY(basegfx::fround(aDiscreteSize.getY()));
129cdf0e10cSrcweir 
130cdf0e10cSrcweir 					if(nSizeX > 0 && nSizeY > 0)
131cdf0e10cSrcweir 					{
132cdf0e10cSrcweir 						// prepare VirtualDevice
133cdf0e10cSrcweir 						VirtualDevice aVirtualDevice(*Application::GetDefaultDevice());
134cdf0e10cSrcweir 						const Size aSizePixel(nSizeX, nSizeY);
135cdf0e10cSrcweir 						aVirtualDevice.SetOutputSizePixel(aSizePixel);
136cdf0e10cSrcweir 
137cdf0e10cSrcweir 						// set size at control
138cdf0e10cSrcweir 						xControlWindow->setPosSize(0, 0, nSizeX, nSizeY, awt::PosSize::POSSIZE);
139cdf0e10cSrcweir 
140cdf0e10cSrcweir 						// get graphics and view
141cdf0e10cSrcweir 						uno::Reference< awt::XGraphics > xGraphics(aVirtualDevice.CreateUnoGraphics());
142cdf0e10cSrcweir 						uno::Reference< awt::XView > xControlView(rXControl, uno::UNO_QUERY);
143cdf0e10cSrcweir 
144cdf0e10cSrcweir 						if(xGraphics.is() && xControlView.is())
145cdf0e10cSrcweir 						{
146cdf0e10cSrcweir 							// link graphics and view
147cdf0e10cSrcweir 							xControlView->setGraphics(xGraphics);
148cdf0e10cSrcweir 
149cdf0e10cSrcweir                             {   // #i93162# For painting the control setting a Zoom (using setZoom() at the xControlView)
150cdf0e10cSrcweir                                 // is needed to define the font size. Normally this is done in
151cdf0e10cSrcweir                                 // ViewObjectContactOfUnoControl::createPrimitive2DSequence by using positionControlForPaint().
152cdf0e10cSrcweir                                 // For some reason the difference between MAP_TWIPS and MAP_100TH_MM still plays
153cdf0e10cSrcweir                                 // a role there so that for Draw/Impress/Calc (the MAP_100TH_MM users) i need to set a zoom
154cdf0e10cSrcweir                                 // here, too. The factor includes the needed scale, but is calculated by pure comparisons. It
155cdf0e10cSrcweir                                 // is somehow related to the twips/100thmm relationship.
156cdf0e10cSrcweir                                 bool bUserIs100thmm(false);
157cdf0e10cSrcweir             				    const uno::Reference< awt::XControl > xControl(xControlView, uno::UNO_QUERY);
158cdf0e10cSrcweir 
159cdf0e10cSrcweir                                 if(xControl.is())
160cdf0e10cSrcweir                                 {
161cdf0e10cSrcweir                                     uno::Reference< awt::XWindowPeer > xWindowPeer(xControl->getPeer());
162cdf0e10cSrcweir 
163cdf0e10cSrcweir                                     if(xWindowPeer.is())
164cdf0e10cSrcweir                                     {
165cdf0e10cSrcweir                     			        VCLXWindow* pVCLXWindow = VCLXWindow::GetImplementation(xWindowPeer);
166cdf0e10cSrcweir 
167cdf0e10cSrcweir                                         if(pVCLXWindow)
168cdf0e10cSrcweir                                         {
169cdf0e10cSrcweir                                             Window* pWindow = pVCLXWindow->GetWindow();
170cdf0e10cSrcweir 
171cdf0e10cSrcweir                                             if(pWindow)
172cdf0e10cSrcweir                                             {
173cdf0e10cSrcweir                                                 pWindow = pWindow->GetParent();
174cdf0e10cSrcweir 
175cdf0e10cSrcweir                                                 if(pWindow)
176cdf0e10cSrcweir                                                 {
177cdf0e10cSrcweir                                                     if(MAP_100TH_MM == pWindow->GetMapMode().GetMapUnit())
178cdf0e10cSrcweir                                                     {
179cdf0e10cSrcweir                                                         bUserIs100thmm = true;
180cdf0e10cSrcweir                                                     }
181cdf0e10cSrcweir                                                 }
182cdf0e10cSrcweir                                             }
183cdf0e10cSrcweir                                         }
184cdf0e10cSrcweir                                     }
185cdf0e10cSrcweir                                 }
186cdf0e10cSrcweir 
187cdf0e10cSrcweir                                 if(bUserIs100thmm)
188cdf0e10cSrcweir                                 {
189cdf0e10cSrcweir 					                // calc screen zoom for text display. fFactor is already added indirectly in aDiscreteSize
190cdf0e10cSrcweir 					                basegfx::B2DVector aScreenZoom(
191cdf0e10cSrcweir 						                basegfx::fTools::equalZero(aScale.getX()) ? 1.0 : aDiscreteSize.getX() / aScale.getX(),
192cdf0e10cSrcweir 						                basegfx::fTools::equalZero(aScale.getY()) ? 1.0 : aDiscreteSize.getY() / aScale.getY());
193cdf0e10cSrcweir 					                static double fZoomScale(28.0); // do not ask for this constant factor, but it gets the zoom right
194cdf0e10cSrcweir                                     aScreenZoom *= fZoomScale;
195cdf0e10cSrcweir 
196cdf0e10cSrcweir                                     // set zoom at control view for text scaling
197cdf0e10cSrcweir 	    			                xControlView->setZoom((float)aScreenZoom.getX(), (float)aScreenZoom.getY());
198cdf0e10cSrcweir                                 }
199cdf0e10cSrcweir                             }
200cdf0e10cSrcweir 
201cdf0e10cSrcweir 							try
202cdf0e10cSrcweir 							{
203cdf0e10cSrcweir 								// try to paint it to VirtualDevice
204cdf0e10cSrcweir 								xControlView->draw(0, 0);
205cdf0e10cSrcweir 
206cdf0e10cSrcweir 								// get bitmap
207cdf0e10cSrcweir 							    const Bitmap aContent(aVirtualDevice.GetBitmap(Point(), aSizePixel));
208cdf0e10cSrcweir 
209cdf0e10cSrcweir                                 // to avoid scaling, use the Bitmap pixel size as primitive size
210cdf0e10cSrcweir                                 const Size aBitmapSize(aContent.GetSizePixel());
211cdf0e10cSrcweir                                 basegfx::B2DVector aBitmapSizeLogic(
212cdf0e10cSrcweir                                     rViewInformation.getInverseObjectToViewTransformation() *
213cdf0e10cSrcweir                                     basegfx::B2DVector(aBitmapSize.getWidth() - 1, aBitmapSize.getHeight() - 1));
214cdf0e10cSrcweir 
215cdf0e10cSrcweir                                 if(bScaleUsed)
216cdf0e10cSrcweir                                 {
217cdf0e10cSrcweir                                     // if scaled adapt to scaled size
218cdf0e10cSrcweir                                     aBitmapSizeLogic /= fFactor;
219cdf0e10cSrcweir                                 }
220cdf0e10cSrcweir 
221cdf0e10cSrcweir                                 // short form for scale and translate transformation
222cdf0e10cSrcweir 								const basegfx::B2DHomMatrix aBitmapTransform(basegfx::tools::createScaleTranslateB2DHomMatrix(
223cdf0e10cSrcweir 									aBitmapSizeLogic.getX(), aBitmapSizeLogic.getY(), aTranslate.getX(), aTranslate.getY()));
224cdf0e10cSrcweir 
225cdf0e10cSrcweir                                 // create primitive
226cdf0e10cSrcweir 								xRetval = new BitmapPrimitive2D(BitmapEx(aContent), aBitmapTransform);
227cdf0e10cSrcweir 							}
228cdf0e10cSrcweir 							catch( const uno::Exception& )
229cdf0e10cSrcweir 							{
230cdf0e10cSrcweir 								DBG_UNHANDLED_EXCEPTION();
231cdf0e10cSrcweir 							}
232cdf0e10cSrcweir 						}
233cdf0e10cSrcweir 					}
234cdf0e10cSrcweir 				}
235cdf0e10cSrcweir 			}
236cdf0e10cSrcweir 
237cdf0e10cSrcweir 			return xRetval;
238cdf0e10cSrcweir 		}
239cdf0e10cSrcweir 
createPlaceholderDecomposition(const geometry::ViewInformation2D &) const240cdf0e10cSrcweir 		Primitive2DReference ControlPrimitive2D::createPlaceholderDecomposition(const geometry::ViewInformation2D& /*rViewInformation*/) const
241cdf0e10cSrcweir 		{
242cdf0e10cSrcweir 			// create a gray placeholder hairline polygon in object size
243cdf0e10cSrcweir 			basegfx::B2DRange aObjectRange(0.0, 0.0, 1.0, 1.0);
244cdf0e10cSrcweir 			aObjectRange.transform(getTransform());
245cdf0e10cSrcweir 			const basegfx::B2DPolygon aOutline(basegfx::tools::createPolygonFromRect(aObjectRange));
246cdf0e10cSrcweir 			const basegfx::BColor aGrayTone(0xc0 / 255.0, 0xc0 / 255.0, 0xc0 / 255.0);
247cdf0e10cSrcweir 
248cdf0e10cSrcweir 			// The replacement object may also get a text like 'empty group' here later
249cdf0e10cSrcweir 			Primitive2DReference xRetval(new PolygonHairlinePrimitive2D(aOutline, aGrayTone));
250cdf0e10cSrcweir 
251cdf0e10cSrcweir 			return xRetval;
252cdf0e10cSrcweir 		}
253cdf0e10cSrcweir 
create2DDecomposition(const geometry::ViewInformation2D & rViewInformation) const254cdf0e10cSrcweir 		Primitive2DSequence ControlPrimitive2D::create2DDecomposition(const geometry::ViewInformation2D& rViewInformation) const
255cdf0e10cSrcweir 		{
256cdf0e10cSrcweir 			// try to create a bitmap decomposition. If that fails for some reason,
257cdf0e10cSrcweir 			// at least create a replacement decomposition.
258cdf0e10cSrcweir 			Primitive2DReference xReference(createBitmapDecomposition(rViewInformation));
259cdf0e10cSrcweir 
260cdf0e10cSrcweir 			if(!xReference.is())
261cdf0e10cSrcweir 			{
262cdf0e10cSrcweir 				xReference = createPlaceholderDecomposition(rViewInformation);
263cdf0e10cSrcweir 			}
264cdf0e10cSrcweir 
265cdf0e10cSrcweir 			return Primitive2DSequence(&xReference, 1L);
266cdf0e10cSrcweir 		}
267cdf0e10cSrcweir 
ControlPrimitive2D(const basegfx::B2DHomMatrix & rTransform,const uno::Reference<awt::XControlModel> & rxControlModel)268cdf0e10cSrcweir 		ControlPrimitive2D::ControlPrimitive2D(
269cdf0e10cSrcweir 			const basegfx::B2DHomMatrix& rTransform,
270cdf0e10cSrcweir 			const uno::Reference< awt::XControlModel >& rxControlModel)
271cdf0e10cSrcweir 		:	BufferedDecompositionPrimitive2D(),
272cdf0e10cSrcweir 			maTransform(rTransform),
273cdf0e10cSrcweir 			mxControlModel(rxControlModel),
274cdf0e10cSrcweir 			mxXControl(),
275cdf0e10cSrcweir 			maLastViewScaling()
276cdf0e10cSrcweir 		{
277cdf0e10cSrcweir 		}
278cdf0e10cSrcweir 
ControlPrimitive2D(const basegfx::B2DHomMatrix & rTransform,const uno::Reference<awt::XControlModel> & rxControlModel,const uno::Reference<awt::XControl> & rxXControl)279cdf0e10cSrcweir 		ControlPrimitive2D::ControlPrimitive2D(
280cdf0e10cSrcweir 			const basegfx::B2DHomMatrix& rTransform,
281cdf0e10cSrcweir 			const uno::Reference< awt::XControlModel >& rxControlModel,
282cdf0e10cSrcweir 			const uno::Reference< awt::XControl >& rxXControl)
283cdf0e10cSrcweir 		:	BufferedDecompositionPrimitive2D(),
284cdf0e10cSrcweir 			maTransform(rTransform),
285cdf0e10cSrcweir 			mxControlModel(rxControlModel),
286cdf0e10cSrcweir 			mxXControl(rxXControl),
287cdf0e10cSrcweir 			maLastViewScaling()
288cdf0e10cSrcweir 		{
289cdf0e10cSrcweir 		}
290cdf0e10cSrcweir 
getXControl() const291cdf0e10cSrcweir 		const uno::Reference< awt::XControl >& ControlPrimitive2D::getXControl() const
292cdf0e10cSrcweir 		{
293cdf0e10cSrcweir 			if(!mxXControl.is())
294cdf0e10cSrcweir 			{
295cdf0e10cSrcweir 				const_cast< ControlPrimitive2D* >(this)->createXControl();
296cdf0e10cSrcweir 			}
297cdf0e10cSrcweir 
298cdf0e10cSrcweir 			return mxXControl;
299cdf0e10cSrcweir 		}
300cdf0e10cSrcweir 
operator ==(const BasePrimitive2D & rPrimitive) const301cdf0e10cSrcweir 		bool ControlPrimitive2D::operator==(const BasePrimitive2D& rPrimitive) const
302cdf0e10cSrcweir 		{
303cdf0e10cSrcweir 			// use base class compare operator
304cdf0e10cSrcweir 			if(BufferedDecompositionPrimitive2D::operator==(rPrimitive))
305cdf0e10cSrcweir 			{
306cdf0e10cSrcweir 				const ControlPrimitive2D& rCompare = (ControlPrimitive2D&)rPrimitive;
307cdf0e10cSrcweir 
308cdf0e10cSrcweir 				if(getTransform() == rCompare.getTransform())
309cdf0e10cSrcweir 				{
310cdf0e10cSrcweir                     // check if ControlModel references both are/are not
311cdf0e10cSrcweir                     bool bRetval(getControlModel().is() == rCompare.getControlModel().is());
312cdf0e10cSrcweir 
313cdf0e10cSrcweir                     if(bRetval && getControlModel().is())
314cdf0e10cSrcweir                     {
315cdf0e10cSrcweir 				        // both exist, check for equality
316cdf0e10cSrcweir 				        bRetval = (getControlModel() == rCompare.getControlModel());
317cdf0e10cSrcweir                     }
318cdf0e10cSrcweir 
319cdf0e10cSrcweir                     if(bRetval)
320cdf0e10cSrcweir                     {
321cdf0e10cSrcweir                         // check if XControl references both are/are not
322cdf0e10cSrcweir                         bRetval = (getXControl().is() == rCompare.getXControl().is());
323cdf0e10cSrcweir                     }
324cdf0e10cSrcweir 
325cdf0e10cSrcweir                     if(bRetval && getXControl().is())
326cdf0e10cSrcweir                     {
327cdf0e10cSrcweir 				        // both exist, check for equality
328cdf0e10cSrcweir 				        bRetval = (getXControl() == rCompare.getXControl());
329cdf0e10cSrcweir                     }
330cdf0e10cSrcweir 
331cdf0e10cSrcweir                     return bRetval;
332cdf0e10cSrcweir 				}
333cdf0e10cSrcweir 			}
334cdf0e10cSrcweir 
335cdf0e10cSrcweir 			return false;
336cdf0e10cSrcweir 		}
337cdf0e10cSrcweir 
getB2DRange(const geometry::ViewInformation2D &) const338cdf0e10cSrcweir 		basegfx::B2DRange ControlPrimitive2D::getB2DRange(const geometry::ViewInformation2D& /*rViewInformation*/) const
339cdf0e10cSrcweir 		{
340cdf0e10cSrcweir 			// simply derivate from unit range
341cdf0e10cSrcweir 			basegfx::B2DRange aRetval(0.0, 0.0, 1.0, 1.0);
342cdf0e10cSrcweir 			aRetval.transform(getTransform());
343cdf0e10cSrcweir 			return aRetval;
344cdf0e10cSrcweir 		}
345cdf0e10cSrcweir 
get2DDecomposition(const geometry::ViewInformation2D & rViewInformation) const346cdf0e10cSrcweir 		Primitive2DSequence ControlPrimitive2D::get2DDecomposition(const geometry::ViewInformation2D& rViewInformation) const
347cdf0e10cSrcweir 		{
348cdf0e10cSrcweir 			// this primitive is view-dependent related to the scaling. If scaling has changed,
349cdf0e10cSrcweir 			// destroy existing decomposition. To detect change, use size of unit size in view coordinates
350cdf0e10cSrcweir 			::osl::MutexGuard aGuard( m_aMutex );
351cdf0e10cSrcweir 			const basegfx::B2DVector aNewScaling(rViewInformation.getObjectToViewTransformation() * basegfx::B2DVector(1.0, 1.0));
352cdf0e10cSrcweir 
353cdf0e10cSrcweir 			if(getBuffered2DDecomposition().hasElements())
354cdf0e10cSrcweir 			{
355cdf0e10cSrcweir 				if(!maLastViewScaling.equal(aNewScaling))
356cdf0e10cSrcweir 				{
357cdf0e10cSrcweir 					// conditions of last local decomposition have changed, delete
358cdf0e10cSrcweir 					const_cast< ControlPrimitive2D* >(this)->setBuffered2DDecomposition(Primitive2DSequence());
359cdf0e10cSrcweir 				}
360cdf0e10cSrcweir 			}
361cdf0e10cSrcweir 
362cdf0e10cSrcweir 			if(!getBuffered2DDecomposition().hasElements())
363cdf0e10cSrcweir 			{
364cdf0e10cSrcweir 				// remember ViewTransformation
365cdf0e10cSrcweir 				const_cast< ControlPrimitive2D* >(this)->maLastViewScaling = aNewScaling;
366cdf0e10cSrcweir 			}
367cdf0e10cSrcweir 
368cdf0e10cSrcweir 			// use parent implementation
369cdf0e10cSrcweir 			return BufferedDecompositionPrimitive2D::get2DDecomposition(rViewInformation);
370cdf0e10cSrcweir 		}
371cdf0e10cSrcweir 
372cdf0e10cSrcweir 		// provide unique ID
373cdf0e10cSrcweir 		ImplPrimitrive2DIDBlock(ControlPrimitive2D, PRIMITIVE2D_ID_CONTROLPRIMITIVE2D)
374cdf0e10cSrcweir 
375cdf0e10cSrcweir 	} // end of namespace primitive2d
376cdf0e10cSrcweir } // end of namespace drawinglayer
377cdf0e10cSrcweir 
378cdf0e10cSrcweir //////////////////////////////////////////////////////////////////////////////
379cdf0e10cSrcweir // eof
380