1 /*************************************************************************
3 * OpenOffice.org - a multi-platform office productivity suite
5 * $RCSfile: controlprimitive2d.cxx,v $
9 * last change: $Author: aw $ $Date: 2008-06-24 15:31:08 $
11 * The Contents of this file are made available subject to
12 * the terms of GNU Lesser General Public License Version 2.1.
15 * GNU Lesser General Public License Version 2.1
16 * =============================================
17 * Copyright 2005 by Sun Microsystems, Inc.
18 * 901 San Antonio Road, Palo Alto, CA 94303, USA
20 * This library is free software; you can redistribute it and/or
21 * modify it under the terms of the GNU Lesser General Public
22 * License version 2.1, as published by the Free Software Foundation.
24 * This library is distributed in the hope that it will be useful,
25 * but WITHOUT ANY WARRANTY; without even the implied warranty of
26 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
27 * Lesser General Public License for more details.
29 * You should have received a copy of the GNU Lesser General Public
30 * License along with this library; if not, write to the Free Software
31 * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
34 ************************************************************************/
36 // MARKER(update_precomp.py): autogen include statement, do not remove
37 #include "precompiled_drawinglayer.hxx"
39 #include <drawinglayer/primitive2d/controlprimitive2d.hxx>
40 #include <com/sun/star/beans/XPropertySet.hpp>
41 #include <comphelper/processfactory.hxx>
42 #include <com/sun/star/awt/XWindow2.hpp>
43 #include <drawinglayer/geometry/viewinformation2d.hxx>
44 #include <vcl/virdev.hxx>
45 #include <vcl/svapp.hxx>
46 #include <com/sun/star/awt/PosSize.hpp>
47 #include <vcl/bitmapex.hxx>
48 #include <drawinglayer/primitive2d/bitmapprimitive2d.hxx>
49 #include <tools/diagnose_ex.h>
50 #include <basegfx/polygon/b2dpolygontools.hxx>
51 #include <basegfx/polygon/b2dpolygon.hxx>
52 #include <drawinglayer/primitive2d/polygonprimitive2d.hxx>
53 #include <drawinglayer/primitive2d/drawinglayer_primitivetypes2d.hxx>
54 #include <svtools/optionsdrawinglayer.hxx>
55 #include <toolkit/awt/vclxwindow.hxx>
56 #include <vcl/window.hxx>
58 //////////////////////////////////////////////////////////////////////////////
60 using namespace com::sun::star
;
62 //////////////////////////////////////////////////////////////////////////////
64 namespace drawinglayer
68 void ControlPrimitive2D::createXControl()
70 if(!mxXControl
.is() && getControlModel().is())
72 uno::Reference
< beans::XPropertySet
> xSet(getControlModel(), uno::UNO_QUERY
);
76 uno::Any
aValue(xSet
->getPropertyValue(rtl::OUString::createFromAscii("DefaultControl")));
77 rtl::OUString aUnoControlTypeName
;
79 if(aValue
>>= aUnoControlTypeName
)
81 if(aUnoControlTypeName
.getLength())
83 uno::Reference
< lang::XMultiServiceFactory
> xFactory( comphelper::getProcessServiceFactory() );
87 uno::Reference
< awt::XControl
> xXControl(xFactory
->createInstance(aUnoControlTypeName
), uno::UNO_QUERY
);
91 xXControl
->setModel(getControlModel());
94 mxXControl
= xXControl
;
103 Primitive2DReference
ControlPrimitive2D::createBitmapDecomposition(const geometry::ViewInformation2D
& rViewInformation
) const
105 Primitive2DReference xRetval
;
106 const uno::Reference
< awt::XControl
>& rXControl(getXControl());
110 uno::Reference
< awt::XWindow
> xControlWindow(rXControl
, uno::UNO_QUERY
);
112 if(xControlWindow
.is())
114 // get decomposition to get size
115 basegfx::B2DVector aScale
, aTranslate
;
116 double fRotate
, fShearX
;
117 getTransform().decompose(aScale
, aTranslate
, fRotate
, fShearX
);
119 // get absolute discrete size (no mirror or rotate here)
120 aScale
= basegfx::absolute(aScale
);
121 basegfx::B2DVector
aDiscreteSize(rViewInformation
.getObjectToViewTransformation() * aScale
);
123 // limit to a maximum square size, e.g. 300x150 pixels (45000)
124 const SvtOptionsDrawinglayer aDrawinglayerOpt
;
125 const double fDiscreteMax(aDrawinglayerOpt
.GetQuadraticFormControlRenderLimit());
126 const double fDiscreteQuadratic(aDiscreteSize
.getX() * aDiscreteSize
.getY());
127 const bool bScaleUsed(fDiscreteQuadratic
> fDiscreteMax
);
132 // get factor and adapt to scaled size
133 fFactor
= sqrt(fDiscreteMax
/ fDiscreteQuadratic
);
134 aDiscreteSize
*= fFactor
;
138 const sal_Int32
nSizeX(basegfx::fround(aDiscreteSize
.getX()));
139 const sal_Int32
nSizeY(basegfx::fround(aDiscreteSize
.getY()));
141 if(nSizeX
> 0 && nSizeY
> 0)
143 // prepare VirtualDevice
144 VirtualDevice
aVirtualDevice(*Application::GetDefaultDevice());
145 const Size
aSizePixel(nSizeX
, nSizeY
);
146 aVirtualDevice
.SetOutputSizePixel(aSizePixel
);
148 // set size at control
149 xControlWindow
->setPosSize(0, 0, nSizeX
, nSizeY
, awt::PosSize::POSSIZE
);
151 // get graphics and view
152 uno::Reference
< awt::XGraphics
> xGraphics(aVirtualDevice
.CreateUnoGraphics());
153 uno::Reference
< awt::XView
> xControlView(rXControl
, uno::UNO_QUERY
);
155 if(xGraphics
.is() && xControlView
.is())
157 // link graphics and view
158 xControlView
->setGraphics(xGraphics
);
160 { // #i93162# For painting the control setting a Zoom (using setZoom() at the xControlView)
161 // is needed to define the font size. Normally this is done in
162 // ViewObjectContactOfUnoControl::createPrimitive2DSequence by using positionControlForPaint().
163 // For some reason the difference between MAP_TWIPS and MAP_100TH_MM still plays
164 // a role there so that for Draw/Impress/Calc (the MAP_100TH_MM users) i need to set a zoom
165 // here, too. The factor includes the needed scale, but is calculated by pure comparisons. It
166 // is somehow related to the twips/100thmm relationship.
167 bool bUserIs100thmm(false);
168 const uno::Reference
< awt::XControl
> xControl(xControlView
, uno::UNO_QUERY
);
172 uno::Reference
< awt::XWindowPeer
> xWindowPeer(xControl
->getPeer());
176 VCLXWindow
* pVCLXWindow
= VCLXWindow::GetImplementation(xWindowPeer
);
180 Window
* pWindow
= pVCLXWindow
->GetWindow();
184 pWindow
= pWindow
->GetParent();
188 if(MAP_100TH_MM
== pWindow
->GetMapMode().GetMapUnit())
190 bUserIs100thmm
= true;
200 // calc screen zoom for text display. fFactor is already added indirectly in aDiscreteSize
201 basegfx::B2DVector
aScreenZoom(
202 basegfx::fTools::equalZero(aScale
.getX()) ? 1.0 : aDiscreteSize
.getX() / aScale
.getX(),
203 basegfx::fTools::equalZero(aScale
.getY()) ? 1.0 : aDiscreteSize
.getY() / aScale
.getY());
204 static double fZoomScale(28.0); // do not ask for this constant factor, but it gets the zoom right
205 aScreenZoom
*= fZoomScale
;
207 // set zoom at control view for text scaling
208 xControlView
->setZoom((float)aScreenZoom
.getX(), (float)aScreenZoom
.getY());
214 // try to paint it to VirtualDevice
215 xControlView
->draw(0, 0);
218 const Bitmap
aContent(aVirtualDevice
.GetBitmap(Point(), aSizePixel
));
220 // to avoid scaling, use the Bitmap pixel size as primitive size
221 const Size
aBitmapSize(aContent
.GetSizePixel());
222 basegfx::B2DVector
aBitmapSizeLogic(
223 rViewInformation
.getInverseObjectToViewTransformation() *
224 basegfx::B2DVector(aBitmapSize
.getWidth() - 1, aBitmapSize
.getHeight() - 1));
228 // if scaled adapt to scaled size
229 aBitmapSizeLogic
/= fFactor
;
232 // short form for scale and translate transformation
233 basegfx::B2DHomMatrix aBitmapTransform
;
235 aBitmapTransform
.set(0L, 0L, aBitmapSizeLogic
.getX());
236 aBitmapTransform
.set(1L, 1L, aBitmapSizeLogic
.getY());
237 aBitmapTransform
.set(0L, 2L, aTranslate
.getX());
238 aBitmapTransform
.set(1L, 2L, aTranslate
.getY());
241 xRetval
= new BitmapPrimitive2D(BitmapEx(aContent
), aBitmapTransform
);
243 catch( const uno::Exception
& )
245 DBG_UNHANDLED_EXCEPTION();
255 Primitive2DReference
ControlPrimitive2D::createPlaceholderDecomposition(const geometry::ViewInformation2D
& /*rViewInformation*/) const
257 // create a gray placeholder hairline polygon in object size
258 basegfx::B2DRange
aObjectRange(0.0, 0.0, 1.0, 1.0);
259 aObjectRange
.transform(getTransform());
260 const basegfx::B2DPolygon
aOutline(basegfx::tools::createPolygonFromRect(aObjectRange
));
261 const basegfx::BColor
aGrayTone(0xc0 / 255.0, 0xc0 / 255.0, 0xc0 / 255.0);
263 // The replacement object may also get a text like 'empty group' here later
264 Primitive2DReference
xRetval(new PolygonHairlinePrimitive2D(aOutline
, aGrayTone
));
269 Primitive2DSequence
ControlPrimitive2D::createLocalDecomposition(const geometry::ViewInformation2D
& rViewInformation
) const
271 // try to create a bitmap decomposition. If that fails for some reason,
272 // at least create a replacement decomposition.
273 Primitive2DReference
xReference(createBitmapDecomposition(rViewInformation
));
277 xReference
= createPlaceholderDecomposition(rViewInformation
);
280 return Primitive2DSequence(&xReference
, 1L);
283 ControlPrimitive2D::ControlPrimitive2D(
284 const basegfx::B2DHomMatrix
& rTransform
,
285 const uno::Reference
< awt::XControlModel
>& rxControlModel
)
287 maTransform(rTransform
),
288 mxControlModel(rxControlModel
),
294 ControlPrimitive2D::ControlPrimitive2D(
295 const basegfx::B2DHomMatrix
& rTransform
,
296 const uno::Reference
< awt::XControlModel
>& rxControlModel
,
297 const uno::Reference
< awt::XControl
>& rxXControl
)
299 maTransform(rTransform
),
300 mxControlModel(rxControlModel
),
301 mxXControl(rxXControl
),
306 const uno::Reference
< awt::XControl
>& ControlPrimitive2D::getXControl() const
310 const_cast< ControlPrimitive2D
* >(this)->createXControl();
316 bool ControlPrimitive2D::operator==(const BasePrimitive2D
& rPrimitive
) const
318 // use base class compare operator
319 if(BasePrimitive2D::operator==(rPrimitive
))
321 const ControlPrimitive2D
& rCompare
= (ControlPrimitive2D
&)rPrimitive
;
323 if(getTransform() == rCompare
.getTransform())
325 // check if ControlModel references both are/are not
326 bool bRetval(getControlModel().is() == rCompare
.getControlModel().is());
328 if(bRetval
&& getControlModel().is())
330 // both exist, check for equality
331 bRetval
= (getControlModel() == rCompare
.getControlModel());
336 // check if XControl references both are/are not
337 bRetval
= (getXControl().is() == rCompare
.getXControl().is());
340 if(bRetval
&& getXControl().is())
342 // both exist, check for equality
343 bRetval
= (getXControl() == rCompare
.getXControl());
353 basegfx::B2DRange
ControlPrimitive2D::getB2DRange(const geometry::ViewInformation2D
& /*rViewInformation*/) const
355 // simply derivate from unit range
356 basegfx::B2DRange
aRetval(0.0, 0.0, 1.0, 1.0);
357 aRetval
.transform(getTransform());
361 Primitive2DSequence
ControlPrimitive2D::get2DDecomposition(const geometry::ViewInformation2D
& rViewInformation
) const
363 // this primitive is view-dependent related to the scaling. If scaling has changed,
364 // destroy existing decomposition. To detect change, use size of unit size in view coordinates
365 ::osl::MutexGuard
aGuard( m_aMutex
);
366 const basegfx::B2DVector
aNewScaling(rViewInformation
.getObjectToViewTransformation() * basegfx::B2DVector(1.0, 1.0));
368 if(getLocalDecomposition().hasElements())
370 if(!maLastViewScaling
.equal(aNewScaling
))
372 // conditions of last local decomposition have changed, delete
373 const_cast< ControlPrimitive2D
* >(this)->setLocalDecomposition(Primitive2DSequence());
377 if(!getLocalDecomposition().hasElements())
379 // remember ViewTransformation
380 const_cast< ControlPrimitive2D
* >(this)->maLastViewScaling
= aNewScaling
;
383 // use parent implementation
384 return BasePrimitive2D::get2DDecomposition(rViewInformation
);
388 ImplPrimitrive2DIDBlock(ControlPrimitive2D
, PRIMITIVE2D_ID_CONTROLPRIMITIVE2D
)
390 } // end of namespace primitive2d
391 } // end of namespace drawinglayer
393 //////////////////////////////////////////////////////////////////////////////